1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file contains functionality to keep track of notifications for players and communicate with external push services |
4
|
|
|
* |
5
|
|
|
* @package BZiON\Models |
6
|
|
|
* @license https://github.com/allejo/bzion/blob/master/LICENSE.md GNU General Public License Version 3 |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
use BZIon\Event\Event; |
10
|
|
|
use BZIon\Event\Events; |
11
|
|
|
use BZIon\Model\Column\Timestamp; |
12
|
|
|
use BZIon\NotificationAdapter\NotificationAdapter; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* A notification to a player |
16
|
|
|
* @package BZiON\Models |
17
|
|
|
*/ |
18
|
|
|
class Notification extends Model |
19
|
|
|
{ |
20
|
|
|
use Timestamp; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* The id of the notified player |
24
|
|
|
* @var int |
25
|
|
|
*/ |
26
|
|
|
protected $receiver; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* The type of the notification |
30
|
|
|
* |
31
|
|
|
* Can be one of the constants in BZIon\Event\Events |
32
|
|
|
* |
33
|
|
|
* @var int |
34
|
|
|
*/ |
35
|
|
|
protected $type; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* The event of the notification |
39
|
|
|
* @var Event |
40
|
|
|
*/ |
41
|
|
|
protected $event; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* The status of the notification (unread, read, deleted) |
45
|
|
|
* @var string |
46
|
|
|
*/ |
47
|
|
|
protected $status; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* When the notification was sent |
51
|
|
|
* @var TimeDate |
52
|
|
|
*/ |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* Services that will be notified when a new notification is created |
56
|
|
|
* @var NotificationAdapter[] |
57
|
|
|
*/ |
58
|
|
|
private static $adapters = array(); |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* The name of the database table used for queries |
62
|
|
|
*/ |
63
|
|
|
const TABLE = "notifications"; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* {@inheritdoc} |
67
|
|
|
*/ |
68
|
1 |
View Code Duplication |
protected function assignResult($notification) |
|
|
|
|
69
|
|
|
{ |
70
|
1 |
|
$this->receiver = $notification['receiver']; |
71
|
1 |
|
$this->type = $notification['type']; |
72
|
1 |
|
$this->event = unserialize($notification['event']); |
73
|
1 |
|
$this->status = $notification['status']; |
74
|
1 |
|
$this->timestamp = TimeDate::fromMysql($notification['timestamp']); |
75
|
1 |
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Enter a new notification into the database |
79
|
|
|
* @param int $receiver The receiver's ID |
80
|
|
|
* @param string $type The type of the notification |
81
|
|
|
* @param Event $event The event of the notification |
82
|
|
|
* @param string $timestamp The timestamp of the notification |
83
|
|
|
* @param string $status The status of the notification (unread, read, deleted) |
84
|
|
|
* @return Notification An object representing the notification that was just entered |
85
|
|
|
*/ |
86
|
1 |
View Code Duplication |
public static function newNotification($receiver, $type, $event, $timestamp = "now", $status = "unread") |
|
|
|
|
87
|
|
|
{ |
88
|
1 |
|
$notification = self::create(array( |
89
|
1 |
|
"receiver" => $receiver, |
90
|
1 |
|
"type" => $type, |
91
|
1 |
|
"event" => serialize($event), |
92
|
1 |
|
"timestamp" => TimeDate::from($timestamp)->toMysql(), |
93
|
|
|
"status" => $status |
94
|
1 |
|
)); |
95
|
|
|
|
96
|
1 |
|
return $notification; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* Show a list of notifications for a specific user |
101
|
|
|
* @param int $receiver The ID of the recipient of the notifications |
102
|
|
|
* @param bool $onlyUnread False to show both unread & read notifications |
103
|
|
|
* @return Notification[] |
104
|
|
|
*/ |
105
|
|
|
public static function getNotifications($receiver, $onlyUnread = false) |
106
|
|
|
{ |
107
|
|
|
$statuses = array('unread'); |
108
|
|
|
if (!$onlyUnread) { |
109
|
|
|
$statuses[] = 'read'; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
return self::getQueryBuilder() |
113
|
|
|
->where('status')->isOneOf($statuses) |
114
|
|
|
->where('receiver')->is($receiver) |
115
|
|
|
->getModels(); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Show the number of notifications the user hasn't read yet |
120
|
|
|
* @param int $receiver |
121
|
|
|
* @return int |
122
|
|
|
*/ |
123
|
1 |
|
public static function countUnreadNotifications($receiver) |
124
|
|
|
{ |
125
|
1 |
|
return self::fetchCount("WHERE receiver = ? AND status = 'unread'", |
126
|
|
|
$receiver |
|
|
|
|
127
|
1 |
|
); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* Get the receiving player of the notification |
132
|
|
|
* @return Player |
133
|
|
|
*/ |
134
|
1 |
|
public function getReceiver() |
135
|
|
|
{ |
136
|
1 |
|
return Player::get($this->receiver); |
137
|
|
|
} |
138
|
|
|
/** |
139
|
|
|
* Get the type of the notification |
140
|
|
|
* |
141
|
|
|
* Do not use Notification::getType(), as it returns the name of the class |
142
|
|
|
* (i.e. notification) |
143
|
|
|
* |
144
|
|
|
* @return int |
145
|
|
|
*/ |
146
|
1 |
|
public function getCategory() |
147
|
|
|
{ |
148
|
1 |
|
return $this->type; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* Get the event of the notification |
153
|
|
|
* @return Event |
154
|
|
|
*/ |
155
|
1 |
|
public function getEvent() |
156
|
|
|
{ |
157
|
1 |
|
return $this->event; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* Finds if the notification has been read by the user |
162
|
|
|
* |
163
|
|
|
* This returns true even if the notification is deleted |
164
|
|
|
* @return bool |
165
|
|
|
*/ |
166
|
1 |
|
public function isRead() |
167
|
|
|
{ |
168
|
1 |
|
return $this->status != "unread"; |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* Mark the notification as read by the user |
173
|
|
|
* @return void |
174
|
|
|
*/ |
175
|
1 |
|
public function markAsRead() |
176
|
|
|
{ |
177
|
1 |
|
if ($this->status == "deleted") { |
178
|
|
|
return; |
179
|
|
|
} |
180
|
|
|
|
181
|
1 |
|
$this->update('status', $this->status = "read"); |
182
|
1 |
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Make sure that the user is shown the notification immediately if they are |
186
|
|
|
* browsing |
187
|
|
|
*/ |
188
|
|
|
public function push() |
189
|
|
|
{ |
190
|
|
|
self::pushEvent('notification', $this); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Get the available actions for the notification |
195
|
|
|
* |
196
|
|
|
* @param bool $email Whether actions should be formatted for e-mails |
197
|
|
|
* @return array |
198
|
|
|
*/ |
199
|
|
|
public function getActions($email = false) |
200
|
|
|
{ |
201
|
|
|
switch ($this->type) { |
202
|
|
|
case Events::TEAM_INVITE: |
203
|
|
|
return array( |
204
|
|
|
($email) ? 'Accept invitation' : 'Accept' => $this->event->getInvitation()->getUrl('accept', $email) |
|
|
|
|
205
|
|
|
); |
206
|
|
|
default: |
207
|
|
|
return array(); |
208
|
|
|
} |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* Push an event to the event adapters |
213
|
|
|
* @param string $type The type of the event |
214
|
|
|
* @param mixed $data The data for the event |
215
|
|
|
* @return void |
216
|
|
|
*/ |
217
|
1 |
|
public static function pushEvent($type, $data = null) |
218
|
|
|
{ |
219
|
|
|
switch ($type) { |
220
|
1 |
|
case 'message': |
221
|
|
|
$message = array( |
222
|
1 |
|
'conversation' => $data['message']->getConversation()->getId(), |
223
|
1 |
|
'message' => $data['message']->getId(), |
224
|
1 |
|
'author' => $data['message']->getAuthor()->getId(), |
225
|
1 |
|
'recipients' => $data['recipients'] |
226
|
1 |
|
); |
227
|
1 |
|
break; |
228
|
|
|
case 'notification': |
229
|
|
|
$message = array( |
230
|
|
|
'type' => $data->getType(), |
231
|
|
|
'receiver' => $data->getReceiver()->getId(), |
232
|
|
|
'notification' => $data->getId() |
233
|
|
|
); |
234
|
|
|
break; |
235
|
|
|
case 'blank': |
236
|
|
|
$message = null; |
237
|
|
|
break; |
238
|
|
|
default: |
239
|
|
|
$message = $data; |
240
|
|
|
} |
241
|
|
|
|
242
|
1 |
|
foreach (self::$adapters as $adapter) { |
243
|
|
|
$adapter->trigger($type, $message); |
244
|
1 |
|
} |
245
|
1 |
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* Initialize the external push adapters |
249
|
|
|
* @return void |
250
|
|
|
*/ |
251
|
1 |
|
public static function initializeAdapters() |
252
|
|
|
{ |
253
|
1 |
|
if (self::$adapters) { |
|
|
|
|
254
|
|
|
// The adapters have already been initialized, no need to do anything! |
255
|
|
|
return; |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
$adapters = array( |
259
|
|
|
'BZIon\NotificationAdapter\WebSocketAdapter' |
260
|
1 |
|
); |
261
|
|
|
|
262
|
1 |
|
foreach ($adapters as $adapter) { |
263
|
1 |
|
if ($adapter::isEnabled()) { |
264
|
|
|
self::$adapters[] = new $adapter(); |
265
|
|
|
} |
266
|
1 |
|
} |
267
|
1 |
|
} |
268
|
|
|
|
269
|
|
|
/** |
270
|
|
|
* {@inheritdoc} |
271
|
|
|
*/ |
272
|
|
|
public static function getActiveStatuses() |
273
|
|
|
{ |
274
|
|
|
return array('read', 'unread'); |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
/** |
278
|
|
|
* Get a query builder for notifications |
279
|
|
|
* @return NotificationQueryBuilder |
280
|
|
|
*/ |
281
|
|
|
public static function getQueryBuilder() |
282
|
|
|
{ |
283
|
|
|
return new NotificationQueryBuilder('Notification', array( |
284
|
|
|
'columns' => array( |
285
|
|
|
'receiver' => 'receiver', |
286
|
|
|
'timestamp' => 'timestamp', |
287
|
|
|
'status' => 'status' |
288
|
|
|
) |
289
|
|
|
)); |
290
|
|
|
} |
291
|
|
|
} |
292
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.