1 | <?php |
||
2 | |||
3 | /** |
||
4 | * This file contains just the functions that turn on and off notifications |
||
5 | * to topics or boards. |
||
6 | * |
||
7 | * @package ElkArte Forum |
||
8 | * @copyright ElkArte Forum contributors |
||
9 | * @license BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file) |
||
10 | * |
||
11 | * This file contains code covered by: |
||
12 | * copyright: 2011 Simple Machines (http://www.simplemachines.org) |
||
13 | * |
||
14 | * @version 2.0 dev |
||
15 | * |
||
16 | */ |
||
17 | |||
18 | namespace ElkArte\Controller; |
||
19 | |||
20 | use ElkArte\AbstractController; |
||
21 | use ElkArte\Action; |
||
22 | use ElkArte\Exceptions\Exception; |
||
23 | use ElkArte\Languages\Txt; |
||
24 | |||
25 | /** |
||
26 | * Functions that turn on and off various member notifications |
||
27 | */ |
||
28 | class Notify extends AbstractController |
||
29 | { |
||
30 | /** |
||
31 | * Pre Dispatch, called before other methods, used to load common needs. |
||
32 | */ |
||
33 | public function pre_dispatch() |
||
34 | { |
||
35 | // Our topic functions are here |
||
36 | require_once(SUBSDIR . '/Topic.subs.php'); |
||
37 | require_once(SUBSDIR . '/Boards.subs.php'); |
||
38 | } |
||
39 | |||
40 | /** |
||
41 | * Dispatch to the right action. |
||
42 | * |
||
43 | * @see AbstractController::action_index |
||
44 | */ |
||
45 | public function action_index() |
||
46 | { |
||
47 | // The number of choices is boggling, ok there are just 2 |
||
48 | $subActions = array( |
||
49 | 'notify' => array($this, 'action_notify'), |
||
50 | 'unsubscribe' => array($this, 'action_unsubscribe'), |
||
51 | ); |
||
52 | |||
53 | // We like action, so lets get ready for some |
||
54 | $action = new Action('notify'); |
||
55 | |||
56 | // Get the subAction, or just go to action_notify |
||
57 | $subAction = $action->initialize($subActions, 'notify'); |
||
58 | |||
59 | // forward to our respective method. |
||
60 | $action->dispatch($subAction); |
||
61 | } |
||
62 | |||
63 | /** |
||
64 | * Turn off/on notification for a particular topic. |
||
65 | * |
||
66 | * What it does: |
||
67 | * |
||
68 | * - Must be called with a topic specified in the URL. |
||
69 | * - The sub-action can be 'on', 'off', or nothing for what to do. |
||
70 | * - Requires the mark_any_notify permission. |
||
71 | * - Upon successful completion of action will direct user back to topic. |
||
72 | * - Accessed via ?action=notify. |
||
73 | * |
||
74 | * @uses Notify.template, main sub-template |
||
75 | */ |
||
76 | public function action_notify() |
||
77 | { |
||
78 | global $topic, $txt, $context; |
||
79 | |||
80 | // Make sure they aren't a guest or something - guests can't really receive notifications! |
||
81 | is_not_guest(); |
||
82 | isAllowedTo('mark_any_notify'); |
||
83 | |||
84 | // Api ajax call? |
||
85 | if ($this->getApi() === 'xml') |
||
86 | { |
||
87 | $this->action_notify_api(); |
||
88 | return true; |
||
89 | } |
||
90 | |||
91 | // Make sure the topic has been specified. |
||
92 | if (empty($topic)) |
||
93 | { |
||
94 | throw new Exception('not_a_topic', false); |
||
95 | } |
||
96 | |||
97 | // What do we do? Better ask if they didn't say.. |
||
98 | if (empty($this->_req->query->sa)) |
||
99 | { |
||
100 | // Load the template, but only if it is needed. |
||
101 | theme()->getTemplates()->load('Notify'); |
||
102 | |||
103 | // Find out if they have notification set for this topic already. |
||
104 | $context['notification_set'] = hasTopicNotification($this->user->id, $topic); |
||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||
105 | |||
106 | // Set the template variables... |
||
107 | $context['topic_href'] = getUrl('action', ['topic' => $topic . '.' . $this->_req->query->start]); |
||
108 | $context['start'] = $this->_req->query->start; |
||
109 | $context['page_title'] = $txt['notifications']; |
||
110 | $context['sub_template'] = 'notification_settings'; |
||
111 | |||
112 | return true; |
||
113 | } |
||
114 | |||
115 | checkSession('get'); |
||
116 | $this->_toggle_topic_notification(); |
||
117 | |||
118 | // Send them back to the topic. |
||
119 | redirectexit('topic=' . $topic . '.' . $this->_req->query->start); |
||
120 | |||
121 | return true; |
||
122 | } |
||
123 | |||
124 | /** |
||
125 | * Toggle a topic notification on/off |
||
126 | */ |
||
127 | private function _toggle_topic_notification($memID = null) |
||
128 | { |
||
129 | global $topic; |
||
130 | |||
131 | // Attempt to turn notifications on/off. |
||
132 | setTopicNotification($memID ?? $this->user->id, $topic, $this->_req->query->sa === 'on'); |
||
0 ignored issues
–
show
The property
id does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||
133 | } |
||
134 | |||
135 | /** |
||
136 | * Turn off/on notifications for a particular topic |
||
137 | * |
||
138 | * - Intended for use in XML or JSON calls |
||
139 | */ |
||
140 | public function action_notify_api() |
||
141 | { |
||
142 | global $topic, $txt, $context; |
||
143 | |||
144 | theme()->getTemplates()->load('Xml'); |
||
145 | |||
146 | theme()->getLayers()->removeAll(); |
||
147 | $context['sub_template'] = 'generic_xml_buttons'; |
||
148 | |||
149 | // Even with Ajax, guests still can't do this |
||
150 | if ($this->user->is_guest) |
||
0 ignored issues
–
show
The property
is_guest does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||
151 | { |
||
152 | Txt::load('Errors'); |
||
153 | $context['xml_data'] = array( |
||
154 | 'error' => 1, |
||
155 | 'text' => $txt['not_guests'] |
||
156 | ); |
||
157 | |||
158 | return; |
||
159 | } |
||
160 | |||
161 | // And members still need the right permissions |
||
162 | if (!allowedTo('mark_any_notify') || empty($topic) || empty($this->_req->query->sa)) |
||
163 | { |
||
164 | Txt::load('Errors'); |
||
165 | $context['xml_data'] = array( |
||
166 | 'error' => 1, |
||
167 | 'text' => $txt['cannot_mark_any_notify'] |
||
168 | ); |
||
169 | |||
170 | return; |
||
171 | } |
||
172 | |||
173 | // And sessions still matter, so you better have a valid one |
||
174 | if (checkSession('get', '', false)) |
||
175 | { |
||
176 | Txt::load('Errors'); |
||
177 | $context['xml_data'] = array( |
||
178 | 'error' => 1, |
||
179 | 'url' => getUrl('action', ['action' => 'notify', 'sa' => ($this->_req->query->sa === 'on' ? 'on' : 'off'), 'topic' => $topic . '.' . $this->_req->query->start, '{session_data}']), |
||
180 | ); |
||
181 | |||
182 | return; |
||
183 | } |
||
184 | |||
185 | $this->_toggle_topic_notification(); |
||
186 | |||
187 | // Return the results so the UI can be updated properly |
||
188 | $context['xml_data'] = array( |
||
189 | 'text' => $this->_req->query->sa === 'on' ? $txt['unnotify'] : $txt['notify'], |
||
190 | 'url' => getUrl('action', ['action' => 'notify', 'sa' => ($this->_req->query->sa === 'on' ? 'off' : 'on'), 'topic' => $topic . '.' . $this->_req->query->start, '{session_data}', 'api' => '1']), |
||
191 | 'confirm' => $this->_req->query->sa === 'on' ? $txt['notification_disable_topic'] : $txt['notification_enable_topic'] |
||
192 | ); |
||
193 | } |
||
194 | |||
195 | /** |
||
196 | * Turn off/on notification for a particular board. |
||
197 | * |
||
198 | * What it does: |
||
199 | * |
||
200 | * - Must be called with a board specified in the URL. |
||
201 | * - Only uses the template if no sub action is used. (on/off) |
||
202 | * - Requires the mark_notify permission. |
||
203 | * - Redirects the user back to the board after it is done. |
||
204 | * - Accessed via ?action=notifyboard. |
||
205 | * |
||
206 | * @uses template_notify_board() sub-template in Notify.template |
||
207 | */ |
||
208 | public function action_notifyboard() |
||
209 | { |
||
210 | global $txt, $board, $context; |
||
211 | |||
212 | // Api ajax call? |
||
213 | if ($this->getApi() === 'xml') |
||
214 | { |
||
215 | $this->action_notifyboard_api(); |
||
216 | return true; |
||
217 | } |
||
218 | |||
219 | // Permissions are an important part of anything ;). |
||
220 | is_not_guest(); |
||
221 | isAllowedTo('mark_notify'); |
||
222 | |||
223 | // You have to specify a board to turn notifications on! |
||
224 | if (empty($board)) |
||
225 | { |
||
226 | throw new Exception('no_board', false); |
||
227 | } |
||
228 | |||
229 | // No subaction: find out what to do. |
||
230 | if (empty($this->_req->query->sa)) |
||
231 | { |
||
232 | // We're gonna need the notify template... |
||
233 | theme()->getTemplates()->load('Notify'); |
||
234 | |||
235 | // Find out if they have notification set for this board already. |
||
236 | $context['notification_set'] = hasBoardNotification($this->user->id, $board); |
||
0 ignored issues
–
show
The property
id does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||
237 | |||
238 | // Set the template variables... |
||
239 | $context['board_href'] = getUrl('action', ['board' => $board . '.' . $this->_req->query->start]); |
||
240 | $context['start'] = $this->_req->query->start; |
||
241 | $context['page_title'] = $txt['notifications']; |
||
242 | $context['sub_template'] = 'notify_board'; |
||
243 | |||
244 | return; |
||
245 | } |
||
246 | |||
247 | checkSession('get'); |
||
248 | |||
249 | // Turn notification on/off for this board. |
||
250 | $this->_toggle_board_notification(); |
||
251 | |||
252 | // Back to the board! |
||
253 | redirectexit('board=' . $board . '.' . $this->_req->query->start); |
||
254 | } |
||
255 | |||
256 | /** |
||
257 | * Toggle a board notification on/off |
||
258 | */ |
||
259 | private function _toggle_board_notification($memID = null) |
||
260 | { |
||
261 | global $board; |
||
262 | |||
263 | // Our board functions are here |
||
264 | require_once(SUBSDIR . '/Boards.subs.php'); |
||
265 | |||
266 | // Turn notification on/off for this board. |
||
267 | setBoardNotification($memID ?? $this->user->id, $board, $this->_req->query->sa === 'on'); |
||
0 ignored issues
–
show
The property
id does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||
268 | } |
||
269 | |||
270 | /** |
||
271 | * Turn off/on notification for a particular board. |
||
272 | * |
||
273 | * - Intended for use in XML or JSON calls |
||
274 | * - Performs the same actions as action_notifyboard but provides ajax responses |
||
275 | */ |
||
276 | public function action_notifyboard_api() |
||
277 | { |
||
278 | global $txt, $board, $context; |
||
279 | |||
280 | theme()->getTemplates()->load('Xml'); |
||
281 | |||
282 | theme()->getLayers()->removeAll(); |
||
283 | $context['sub_template'] = 'generic_xml_buttons'; |
||
284 | |||
285 | // Permissions are an important part of anything ;). |
||
286 | if ($this->user->is_guest) |
||
0 ignored issues
–
show
The property
is_guest does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||
287 | { |
||
288 | Txt::load('Errors'); |
||
289 | $context['xml_data'] = array( |
||
290 | 'error' => 1, |
||
291 | 'text' => $txt['not_guests'] |
||
292 | ); |
||
293 | |||
294 | return; |
||
295 | } |
||
296 | |||
297 | // Have to have provided the right information |
||
298 | if (!allowedTo('mark_notify') || empty($board) || empty($this->_req->query->sa)) |
||
299 | { |
||
300 | Txt::load('Errors'); |
||
301 | $context['xml_data'] = array( |
||
302 | 'error' => 1, |
||
303 | 'text' => $txt['cannot_mark_notify'], |
||
304 | ); |
||
305 | |||
306 | return; |
||
307 | } |
||
308 | |||
309 | // Sessions are always verified |
||
310 | if (checkSession('get', '', false)) |
||
311 | { |
||
312 | Txt::load('Errors'); |
||
313 | $context['xml_data'] = array( |
||
314 | 'error' => 1, |
||
315 | 'url' => getUrl('action', ['action' => 'notifyboard', 'sa' => ($this->_req->query->sa === 'on' ? 'on' : 'off'), 'board' => $board . '.' . $this->_req->query->start, '{session_data}']), |
||
316 | ); |
||
317 | |||
318 | return; |
||
319 | } |
||
320 | |||
321 | $this->_toggle_board_notification(); |
||
322 | |||
323 | $context['xml_data'] = array( |
||
324 | 'text' => $this->_req->query->sa === 'on' ? $txt['unnotify'] : $txt['notify'], |
||
325 | 'url' => getUrl('action', ['action' => 'notifyboard', 'sa' => ($this->_req->query->sa === 'on' ? 'off' : 'on'), 'board' => $board . '.' . $this->_req->query->start, '{session_data}', 'api' => '1'] + (isset($_REQUEST['json']) ? ['json'] : [])), |
||
326 | 'confirm' => $this->_req->query->sa === 'on' ? $txt['notification_disable_board'] : $txt['notification_enable_board'] |
||
327 | ); |
||
328 | } |
||
329 | |||
330 | /** |
||
331 | * Turn off/on unread replies subscription for a topic |
||
332 | * |
||
333 | * What it does: |
||
334 | * |
||
335 | * - Must be called with a topic specified in the URL. |
||
336 | * - The sub-action can be 'on', 'off', or nothing for what to do. |
||
337 | * - Requires the mark_any_notify permission. |
||
338 | * - Upon successful completion of action will direct user back to topic. |
||
339 | * - Accessed via ?action=unwatchtopic. |
||
340 | */ |
||
341 | public function action_unwatchtopic() |
||
342 | { |
||
343 | global $topic, $modSettings; |
||
344 | |||
345 | is_not_guest(); |
||
346 | |||
347 | // Let's do something only if the function is enabled |
||
348 | if ($this->user->is_guest === false && !empty($modSettings['enable_unwatch'])) |
||
0 ignored issues
–
show
The property
is_guest does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||
349 | { |
||
350 | checkSession('get'); |
||
351 | |||
352 | if ($this->getApi() === 'xml') |
||
353 | { |
||
354 | $this->action_unwatchtopic_api(); |
||
355 | return; |
||
356 | } |
||
357 | |||
358 | $this->_toggle_topic_watch(); |
||
359 | } |
||
360 | |||
361 | // Back to the topic. |
||
362 | redirectexit('topic=' . $topic . '.' . $this->_req->query->start); |
||
363 | } |
||
364 | |||
365 | /** |
||
366 | * Toggle a watch topic on/off |
||
367 | */ |
||
368 | private function _toggle_topic_watch() |
||
369 | { |
||
370 | global $topic; |
||
371 | |||
372 | setTopicWatch($this->user->id, $topic, $this->_req->query->sa === 'on'); |
||
0 ignored issues
–
show
The property
id does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||
373 | } |
||
374 | |||
375 | /** |
||
376 | * Turn off/on unread replies subscription for a topic |
||
377 | * |
||
378 | * - Intended for use in XML or JSON calls |
||
379 | */ |
||
380 | public function action_unwatchtopic_api() |
||
381 | { |
||
382 | global $topic, $modSettings, $txt, $context; |
||
383 | |||
384 | theme()->getTemplates()->load('Xml'); |
||
385 | |||
386 | theme()->getLayers()->removeAll(); |
||
387 | $context['sub_template'] = 'generic_xml_buttons'; |
||
388 | |||
389 | // Sorry guests just can't do this |
||
390 | if ($this->user->is_guest) |
||
0 ignored issues
–
show
The property
is_guest does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||
391 | { |
||
392 | Txt::load('Errors'); |
||
393 | $context['xml_data'] = array( |
||
394 | 'error' => 1, |
||
395 | 'text' => $txt['not_guests'] |
||
396 | ); |
||
397 | |||
398 | return; |
||
399 | } |
||
400 | |||
401 | // Let's do something only if the function is enabled |
||
402 | if (empty($modSettings['enable_unwatch'])) |
||
403 | { |
||
404 | Txt::load('Errors'); |
||
405 | $context['xml_data'] = array( |
||
406 | 'error' => 1, |
||
407 | 'text' => $txt['feature_disabled'], |
||
408 | ); |
||
409 | |||
410 | return; |
||
411 | } |
||
412 | |||
413 | // Sessions need to be validated |
||
414 | if (checkSession('get', '', false)) |
||
415 | { |
||
416 | Txt::load('Errors'); |
||
417 | $context['xml_data'] = array( |
||
418 | 'error' => 1, |
||
419 | 'url' => getUrl('action', ['action' => 'unwatchtopic', 'sa' => ($this->_req->query->sa === 'on' ? 'on' : 'off'), 'topic' => $topic . '.' . $this->_req->query->start, '{session_data}']) |
||
420 | ); |
||
421 | |||
422 | return; |
||
423 | } |
||
424 | |||
425 | $this->_toggle_topic_watch(); |
||
426 | |||
427 | $context['xml_data'] = array( |
||
428 | 'text' => $this->_req->query->sa === 'on' ? $txt['watch'] : $txt['unwatch'], |
||
429 | 'url' => getUrl('action', ['action' => 'unwatchtopic', 'sa' => ($this->_req->query->sa === 'on' ? 'off' : 'on'), 'topic' => $context['current_topic'] . '.' . $this->_req->query->start, '{session_data}', 'api' => '1'] + (isset($_REQUEST['json']) ? ['json'] : [])), |
||
430 | ); |
||
431 | |||
432 | setTopicWatch($this->user->id, $topic, $this->_req->query->sa === 'on'); |
||
433 | } |
||
434 | |||
435 | /** |
||
436 | * Accessed via the unsubscribe link provided in site emails. This will then |
||
437 | * unsubscribe the user from a board or a topic (depending on the link) without them |
||
438 | * having to login. |
||
439 | */ |
||
440 | public function action_unsubscribe() |
||
441 | { |
||
442 | // Looks like we need to unsubscribe someone |
||
443 | if ($this->_validateUnsubscribeToken($member, $area, $extra)) |
||
444 | { |
||
445 | $this->_unsubscribeToggle($member, $area, $extra); |
||
446 | $this->_prepareTemplateMessage($area, $extra, $member['email_address']); |
||
447 | |||
448 | return true; |
||
449 | } |
||
450 | |||
451 | // A default msg that we did something and maybe take a chill? |
||
452 | $this->_prepareTemplateMessage('default', '', ''); |
||
453 | |||
454 | // Not the proper message it should not happen either |
||
455 | spamProtection('remind'); |
||
456 | |||
457 | return true; |
||
458 | } |
||
459 | |||
460 | /** |
||
461 | * Does the actual area unsubscribe toggle |
||
462 | * |
||
463 | * @param array $member Member info from getBasicMemberData |
||
464 | * @param string $area area they want to be removed from |
||
465 | * @param string $extra parameters needed for some areas |
||
466 | */ |
||
467 | private function _unsubscribeToggle($member, $area, $extra) |
||
468 | { |
||
469 | global $user_info, $board, $topic; |
||
470 | |||
471 | $baseAreas = ['topic', 'board', 'buddy', 'likemsg', 'mentionmem', 'quotedmem', 'rlikemsg']; |
||
472 | |||
473 | // Not a base method, so an addon will need to process this |
||
474 | if (!in_array($area, $baseAreas)) |
||
475 | { |
||
476 | return $this->_unsubscribeModuleToggle($member, $area, $extra); |
||
477 | } |
||
478 | |||
479 | // Look away while we stuff the old ballet box, power to the people! |
||
480 | $this->_req->query->sa = 'off'; |
||
481 | |||
482 | switch ($area) |
||
483 | { |
||
484 | case 'topic': |
||
485 | $topic = $extra; |
||
486 | $this->_toggle_topic_notification($member['id_member']); |
||
487 | break; |
||
488 | case 'board': |
||
489 | $board = $extra; |
||
490 | $this->_toggle_board_notification($member['id_member']); |
||
491 | break; |
||
492 | case 'buddy': |
||
493 | case 'likemsg': |
||
494 | case 'mentionmem': |
||
495 | case 'quotedmem': |
||
496 | case 'rlikemsg': |
||
497 | $this->_setUserEmailNotificationOff($member['id_member'], $area); |
||
498 | break; |
||
499 | } |
||
500 | |||
501 | return true; |
||
502 | } |
||
503 | |||
504 | /** |
||
505 | * Pass unsubscribe information to the appropriate "addon" mention class/method |
||
506 | * |
||
507 | * @param array $member Member info from getBasicMemberData |
||
508 | * @param string $area area they want to be removed from |
||
509 | * @param string $extra parameters needed for some |
||
510 | * |
||
511 | * @return bool if the $unsubscribe method was called |
||
512 | */ |
||
513 | private function _unsubscribeModuleToggle($member, $area, $extra) |
||
514 | { |
||
515 | $class_name = '\\ElkArte\\Mentions\\MentionType\\Event\\' . ucwords($area); |
||
516 | |||
517 | if (method_exists($class_name, 'unsubscribe')) |
||
518 | { |
||
519 | return (new $class_name)->unsubscribe($member, $area, $extra); |
||
520 | } |
||
521 | |||
522 | return false; |
||
523 | } |
||
524 | |||
525 | /** |
||
526 | * Validates a supplied token and extracts the needed bits |
||
527 | * |
||
528 | * What it does: |
||
529 | * - Checks token conforms to a known pattern |
||
530 | * - Checks token is for a known notification type |
||
531 | * - Checks the age of the token |
||
532 | * - Finds the member claimed in the token |
||
533 | * - Runs crypt on member data to validate it matches the supplied hash |
||
534 | * |
||
535 | * @param array $member Member info from getBasicMemberData |
||
536 | * @param string $area area they want to be removed from |
||
537 | * @param string $extra parameters needed for some areas |
||
538 | * @return bool |
||
539 | */ |
||
540 | private function _validateUnsubscribeToken(&$member, &$area, &$extra) |
||
541 | { |
||
542 | // Token was passed and matches our expected pattern |
||
543 | $token = $this->_req->getQuery('token', 'trim', ''); |
||
544 | $token = urldecode($token); |
||
545 | if (empty($token) || preg_match('~^(\d+_[a-zA-Z0-9./]{32,44}_[^)]*)~m', $token, $match) !== 1) |
||
546 | { |
||
547 | return false; |
||
548 | } |
||
549 | |||
550 | // Load all notification types in the system e.g.buddy, likemsg, etc |
||
551 | require_once(SUBSDIR . '/ManageFeatures.subs.php'); |
||
552 | $potentialAreas = []; |
||
553 | $notification_classes = getAvailableNotifications(); |
||
554 | foreach ($notification_classes as $class) |
||
555 | { |
||
556 | if ($class::canUse() === false) |
||
557 | { |
||
558 | continue; |
||
559 | } |
||
560 | |||
561 | $potentialAreas[] = strtolower($class::getType()); |
||
562 | } |
||
563 | |||
564 | $potentialAreas = array_merge($potentialAreas, ['topic', 'board']); |
||
565 | |||
566 | // Expand the token |
||
567 | [$id_member, $hash, $area, $extra, $time] = explode('_', $match[1]); |
||
568 | |||
569 | // The area is a known one |
||
570 | if (!in_array($area, $potentialAreas, true)) |
||
571 | { |
||
572 | return false; |
||
573 | } |
||
574 | |||
575 | // Not so old, 2 weeks is plenty |
||
576 | if (time() - $time > (60 * 60 * 24 * 14)) |
||
577 | { |
||
578 | return false; |
||
579 | } |
||
580 | |||
581 | // Find the claimed member |
||
582 | require_once(SUBSDIR . '/Members.subs.php'); |
||
583 | $member = getBasicMemberData((int) $id_member, array('authentication' => true)); |
||
584 | if (empty($member)) |
||
585 | { |
||
586 | return false; |
||
587 | } |
||
588 | |||
589 | // Validate the token belongs to this member |
||
590 | require_once(SUBSDIR . '/Notification.subs.php'); |
||
591 | return validateNotifierToken( |
||
592 | $member['email_address'], |
||
593 | $member['password_salt'], |
||
594 | $area . $extra . $time, |
||
595 | $hash |
||
596 | ); |
||
597 | } |
||
598 | |||
599 | /** |
||
600 | * Used to disable email notification of a specific mention area |
||
601 | * |
||
602 | * @param int $memID |
||
603 | * @param string $area buddy, likemsg, mentionmem, quotedmem, rlikemsg |
||
604 | */ |
||
605 | private function _setUserEmailNotificationOff($memID, $area) |
||
606 | { |
||
607 | require_once(SUBSDIR . '/Profile.subs.php'); |
||
608 | Txt::load('Profile'); |
||
609 | |||
610 | $_POST['notify_submit'] = true; |
||
611 | |||
612 | foreach (getMemberNotificationsProfile($memID) as $mention => $data) |
||
613 | { |
||
614 | foreach ($data['data'] as $type => $method) |
||
615 | { |
||
616 | // No email notifications for you |
||
617 | if ($mention === $area && in_array($type, ['email', 'emaildaily', 'emailweekly'])) |
||
618 | { |
||
619 | continue; |
||
620 | } |
||
621 | |||
622 | // All the rest as it was |
||
623 | if ($method['enabled']) |
||
624 | { |
||
625 | $_POST['notify'][$mention]['status'][] = $method['name']; |
||
626 | } |
||
627 | } |
||
628 | } |
||
629 | |||
630 | makeNotificationChanges($memID); |
||
631 | } |
||
632 | |||
633 | /** |
||
634 | * Sets an unsubscribed string for template use |
||
635 | * |
||
636 | * @param string $area |
||
637 | * @param string $extra |
||
638 | */ |
||
639 | private function _prepareTemplateMessage($area, $extra, $email) |
||
640 | { |
||
641 | global $txt, $context; |
||
642 | |||
643 | switch ($area) |
||
644 | { |
||
645 | case 'topic': |
||
646 | require_once(SUBSDIR . '/Topic.subs.php'); |
||
647 | try |
||
648 | { |
||
649 | $subject = getSubject((int) $extra); |
||
650 | $subject = $subject ?? $txt['notify_unsubscribed_generic']; |
||
651 | $context['unsubscribe_message'] = sprintf($txt['notify_topic_unsubscribed'], $subject, $email); |
||
652 | } |
||
653 | catch (Exception) |
||
654 | { |
||
655 | $context['unsubscribe_message'] = $txt['notify_default_unsubscribed']; |
||
656 | } |
||
657 | |||
658 | break; |
||
659 | case 'board': |
||
660 | require_once(SUBSDIR . '/Boards.subs.php'); |
||
661 | $name = boardInfo((int) $extra); |
||
662 | $name = $name === null ? $txt['notify_unsubscribed_generic'] : $name['name']; |
||
0 ignored issues
–
show
|
|||
663 | $context['unsubscribe_message'] = sprintf($txt['notify_board_unsubscribed'], $name, $email); |
||
664 | break; |
||
665 | case 'buddy': |
||
666 | case 'likemsg': |
||
667 | case 'mentionmem': |
||
668 | case 'quotedmem': |
||
669 | case 'rlikemsg': |
||
670 | Txt::load('Mentions'); |
||
671 | $context['unsubscribe_message'] = sprintf($txt['notify_mention_unsubscribed'], $txt['mentions_type_' . $area], $email); |
||
672 | break; |
||
673 | default: |
||
674 | $context['unsubscribe_message'] = $txt['notify_default_unsubscribed']; |
||
675 | break; |
||
676 | } |
||
677 | |||
678 | theme()->getTemplates()->load('Notify'); |
||
679 | $context['page_title'] = $txt['notifications']; |
||
680 | $context['sub_template'] = 'notify_unsubscribe'; |
||
681 | } |
||
682 | } |
||
683 |