Move [Friendica:Notify] to a own PREFIX variable
[friendica.git/.git] / include / enotify.php
1 <?php
2 /**
3  * @file include/enotify.php
4  */
5
6 use Friendica\Content\Text\BBCode;
7 use Friendica\Core\Hook;
8 use Friendica\Core\Logger;
9 use Friendica\Core\Renderer;
10 use Friendica\Core\System;
11 use Friendica\Database\DBA;
12 use Friendica\DI;
13 use Friendica\Model\Item;
14 use Friendica\Model\ItemContent;
15 use Friendica\Model\Notify;
16 use Friendica\Model\User;
17 use Friendica\Model\UserItem;
18 use Friendica\Protocol\Activity;
19
20 /**
21  * Creates a notification entry and possibly sends a mail
22  *
23  * @param array $params Array with the elements:
24  *                      uid, item, parent, type, otype, verb, event,
25  *                      link, subject, body, to_name, to_email, source_name,
26  *                      source_link, activity, preamble, notify_flags,
27  *                      language, show_in_notification_page
28  * @return bool
29  * @throws \Friendica\Network\HTTPException\InternalServerErrorException
30  */
31 function notification($params)
32 {
33         /** @var string the common prefix of a notification subject */
34         $SUBJECT_PREFIX = DI::l10n()->t('[Friendica:Notify]');
35
36         // Temporary logging for finding the origin
37         if (!isset($params['uid'])) {
38                 Logger::notice('Missing parameters "uid".', ['params' => $params, 'callstack' => System::callstack()]);
39         }
40
41         // Ensure that the important fields are set at any time
42         $fields = ['notify-flags', 'language', 'username', 'email'];
43         $user = DBA::selectFirst('user', $fields, ['uid' => $params['uid']]);
44
45         if (!DBA::isResult($user)) {
46                 Logger::error('Unknown user', ['uid' =>  $params['uid']]);
47                 return false;
48         }
49
50         $params['notify_flags'] = ($params['notify_flags'] ?? '') ?: $user['notify-flags'];
51         $params['language']     = ($params['language']     ?? '') ?: $user['language'];
52         $params['to_name']      = ($params['to_name']      ?? '') ?: $user['username'];
53         $params['to_email']     = ($params['to_email']     ?? '') ?: $user['email'];
54
55         // from here on everything is in the recipients language
56         $l10n = DI::l10n()->withLang($params['language']);
57
58         $siteurl = DI::baseUrl()->get(true);
59         $sitename = DI::config()->get('config', 'sitename');
60
61         $hostname = DI::baseUrl()->getHostname();
62         if (strpos($hostname, ':')) {
63                 $hostname = substr($hostname, 0, strpos($hostname, ':'));
64         }
65
66         $user = User::getById($params['uid'], ['nickname', 'page-flags']);
67
68         // There is no need to create notifications for forum accounts
69         if (!DBA::isResult($user) || in_array($user["page-flags"], [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP])) {
70                 return false;
71         }
72         $nickname = $user["nickname"];
73
74         // with $params['show_in_notification_page'] == false, the notification isn't inserted into
75         // the database, and an email is sent if applicable.
76         // default, if not specified: true
77         $show_in_notification_page = isset($params['show_in_notification_page']) ? $params['show_in_notification_page'] : true;
78
79         $additional_mail_header = "X-Friendica-Account: <".$nickname."@".$hostname.">\n";
80
81         if (array_key_exists('item', $params)) {
82                 $title = $params['item']['title'];
83                 $body = $params['item']['body'];
84         } else {
85                 $title = $body = '';
86         }
87
88         if (isset($params['item']['id'])) {
89                 $item_id = $params['item']['id'];
90         } else {
91                 $item_id = 0;
92         }
93
94         if (isset($params['parent'])) {
95                 $parent_id = $params['parent'];
96         } else {
97                 $parent_id = 0;
98         }
99
100         $epreamble = '';
101         $preamble  = '';
102         $subject   = '';
103         $sitelink  = '';
104         $tsitelink = '';
105         $hsitelink = '';
106         $itemlink  = '';
107
108         if ($params['type'] == Notify\Type::MAIL) {
109                 $itemlink = $siteurl.'/message/'.$params['item']['id'];
110                 $params["link"] = $itemlink;
111
112                 $subject = $l10n->t( '%s New mail received at %s', $SUBJECT_PREFIX, $sitename);
113
114                 $preamble = $l10n->t('%1$s sent you a new private message at %2$s.', $params['source_name'], $sitename);
115                 $epreamble = $l10n->t('%1$s sent you %2$s.', '[url='.$params['source_link'].']'.$params['source_name'].'[/url]', '[url=' . $itemlink . ']' . $l10n->t('a private message').'[/url]');
116
117                 $sitelink = $l10n->t('Please visit %s to view and/or reply to your private messages.');
118                 $tsitelink = sprintf($sitelink, $siteurl.'/message/'.$params['item']['id']);
119                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'/message/'.$params['item']['id'].'">'.$sitename.'</a>');
120         }
121
122         if ($params['type'] == Notify\Type::COMMENT || $params['type'] == Notify\Type::TAG_SELF) {
123                 $thread = Item::selectFirstThreadForUser($params['uid'], ['ignored'], ['iid' => $parent_id, 'deleted' => false]);
124                 if (DBA::isResult($thread) && $thread['ignored']) {
125                         Logger::log('Thread ' . $parent_id . ' will be ignored', Logger::DEBUG);
126                         return false;
127                 }
128
129                 // Check to see if there was already a tag notify or comment notify for this post.
130                 // If so don't create a second notification
131                 /// @todo In the future we should store the notification with the highest "value" and replace notifications
132                 $condition = ['type' => [Notify\Type::TAG_SELF, Notify\Type::COMMENT, Notify\Type::SHARE],
133                         'link' => $params['link'], 'uid' => $params['uid']];
134                 if (DBA::exists('notify', $condition)) {
135                         return false;
136                 }
137
138                 // if it's a post figure out who's post it is.
139                 $item = null;
140                 if ($params['otype'] === Notify\ObjectType::ITEM && $parent_id) {
141                         $item = Item::selectFirstForUser($params['uid'], Item::ITEM_FIELDLIST, ['id' => $parent_id, 'deleted' => false]);
142                 }
143
144                 if (empty($item)) {
145                         return false;
146                 }
147
148                 $item_post_type = Item::postType($item);
149
150                 $content = ItemContent::getPlaintextPost($item, 70);
151                 if (!empty($content['text'])) {
152                         $title = '"' . trim(str_replace("\n", " ", $content['text'])) . '"';
153                 } else {
154                         $title = '';
155                 }
156
157                 // First go for the general message
158
159                 // "George Bull's post"
160                 if ($params['activity']['origin_comment']) {
161                         $message = '%1$s replied to you on %2$s\'s %3$s %4$s';
162                 } elseif ($params['activity']['explicit_tagged']) {
163                         $message = '%1$s tagged you on %2$s\'s %3$s %4$s';
164                 } else {
165                         $message = '%1$s commented on %2$s\'s %3$s %4$s';
166                 }
167
168                 $dest_str = $l10n->t($message, $params['source_name'], $item['author-name'], $item_post_type, $title);
169
170                 // Then look for the special cases
171
172                 // "your post"
173                 if ($params['activity']['origin_thread']) {
174                         if ($params['activity']['origin_comment']) {
175                                 $message = '%1$s replied to you on your %2$s %3$s';
176                         } elseif ($params['activity']['explicit_tagged']) {
177                                 $message = '%1$s tagged you on your %2$s %3$s';
178                         } else {
179                                 $message = '%1$s commented on your %2$s %3$s';
180                         }
181
182                         $dest_str = $l10n->t($message, $params['source_name'], $item_post_type, $title);
183                 // "their post"
184                 } elseif ($item['author-link'] == $params['source_link']) {
185                         if ($params['activity']['origin_comment']) {
186                                 $message = '%1$s replied to you on their %2$s %3$s';
187                         } elseif ($params['activity']['explicit_tagged']) {
188                                 $message = '%1$s tagged you on their %2$s %3$s';
189                         } else {
190                                 $message = '%1$s commented on their %2$s %3$s';
191                         }
192
193                         $dest_str = $l10n->t($message, $params['source_name'], $item_post_type, $title);
194                 }
195
196                 // Some mail software relies on subject field for threading.
197                 // So, we cannot have different subjects for notifications of the same thread.
198                 // Before this we have the name of the replier on the subject rendering
199                 // different subjects for messages on the same thread.
200                 if ($params['activity']['explicit_tagged']) {
201                         $subject = $l10n->t('%s %s tagged you', $SUBJECT_PREFIX, $params['source_name']);
202
203                         $preamble = $l10n->t('%1$s tagged you at %2$s', $params['source_name'], $sitename);
204                 } else {
205                         $subject = $l10n->t('%s Comment to conversation #%1$d by %2$s', $SUBJECT_PREFIX, $parent_id, $params['source_name']);
206
207                         $preamble = $l10n->t('%s commented on an item/conversation you have been following.', $params['source_name']);
208                 }
209
210                 $epreamble = $dest_str;
211
212                 $sitelink = $l10n->t('Please visit %s to view and/or reply to the conversation.');
213                 $tsitelink = sprintf($sitelink, $siteurl);
214                 $hsitelink = sprintf($sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
215                 $itemlink =  $params['link'];
216         }
217
218         if ($params['type'] == Notify\Type::WALL) {
219                 $subject = $l10n->t('%s %s posted to your profile wall', $SUBJECT_PREFIX, $params['source_name']);
220
221                 $preamble = $l10n->t('%1$s posted to your profile wall at %2$s', $params['source_name'], $sitename);
222                 $epreamble = $l10n->t('%1$s posted to [url=%2$s]your wall[/url]',
223                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
224                         $params['link']
225                 );
226
227                 $sitelink = $l10n->t('Please visit %s to view and/or reply to the conversation.');
228                 $tsitelink = sprintf($sitelink, $siteurl);
229                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
230                 $itemlink =  $params['link'];
231         }
232
233         if ($params['type'] == Notify\Type::SHARE) {
234                 $subject = $l10n->t('%s Friendica:Notify] %s shared a new post', $SUBJECT_PREFIX, $params['source_name']);
235
236                 $preamble = $l10n->t('%1$s shared a new post at %2$s', $params['source_name'], $sitename);
237                 $epreamble = $l10n->t('%1$s [url=%2$s]shared a post[/url].',
238                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
239                         $params['link']
240                 );
241
242                 $sitelink = $l10n->t('Please visit %s to view and/or reply to the conversation.');
243                 $tsitelink = sprintf($sitelink, $siteurl);
244                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
245                 $itemlink =  $params['link'];
246         }
247
248         if ($params['type'] == Notify\Type::POKE) {
249                 $subject = $l10n->t('%s %1$s poked you', $SUBJECT_PREFIX, $params['source_name']);
250
251                 $preamble = $l10n->t('%1$s poked you at %2$s', $params['source_name'], $sitename);
252                 $epreamble = $l10n->t('%1$s [url=%2$s]poked you[/url].',
253                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
254                         $params['link']
255                 );
256
257                 $subject = str_replace('poked', $l10n->t($params['activity']), $subject);
258                 $preamble = str_replace('poked', $l10n->t($params['activity']), $preamble);
259                 $epreamble = str_replace('poked', $l10n->t($params['activity']), $epreamble);
260
261                 $sitelink = $l10n->t('Please visit %s to view and/or reply to the conversation.');
262                 $tsitelink = sprintf($sitelink, $siteurl);
263                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
264                 $itemlink =  $params['link'];
265         }
266
267         if ($params['type'] == Notify\Type::TAG_SHARE) {
268                 $itemlink =  $params['link'];
269                 $subject = $l10n->t('%s %s tagged your post', $SUBJECT_PREFIX, $params['source_name']);
270
271                 $preamble = $l10n->t('%1$s tagged your post at %2$s', $params['source_name'], $sitename);
272                 $epreamble = $l10n->t('%1$s tagged [url=%2$s]your post[/url]',
273                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
274                         $itemlink
275                 );
276
277                 $sitelink = $l10n->t('Please visit %s to view and/or reply to the conversation.');
278                 $tsitelink = sprintf($sitelink, $siteurl);
279                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
280         }
281
282         if ($params['type'] == Notify\Type::INTRO) {
283                 $itemlink = $params['link'];
284                 $subject = $l10n->t('%s Introduction received', $SUBJECT_PREFIX);
285
286                 $preamble = $l10n->t('You\'ve received an introduction from \'%1$s\' at %2$s', $params['source_name'], $sitename);
287                 $epreamble = $l10n->t('You\'ve received [url=%1$s]an introduction[/url] from %2$s.',
288                         $itemlink,
289                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]'
290                 );
291
292                 $body = $l10n->t('You may visit their profile at %s', $params['source_link']);
293
294                 $sitelink = $l10n->t('Please visit %s to approve or reject the introduction.');
295                 $tsitelink = sprintf($sitelink, $siteurl);
296                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
297
298                 switch ($params['verb']) {
299                         case Activity::FRIEND:
300                                 // someone started to share with user (mostly OStatus)
301                                 $subject = $l10n->t('%s A new person is sharing with you', $SUBJECT_PREFIX);
302
303                                 $preamble = $l10n->t('%1$s is sharing with you at %2$s', $params['source_name'], $sitename);
304                                 $epreamble = $l10n->t('%1$s is sharing with you at %2$s',
305                                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
306                                         $sitename
307                                 );
308                                 break;
309                         case Activity::FOLLOW:
310                                 // someone started to follow the user (mostly OStatus)
311                                 $subject = $l10n->t('%s You have a new follower', $SUBJECT_PREFIX);
312
313                                 $preamble = $l10n->t('You have a new follower at %2$s : %1$s', $params['source_name'], $sitename);
314                                 $epreamble = $l10n->t('You have a new follower at %2$s : %1$s',
315                                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
316                                         $sitename
317                                 );
318                                 break;
319                         default:
320                                 // ACTIVITY_REQ_FRIEND is default activity for notifications
321                                 break;
322                 }
323         }
324
325         if ($params['type'] == Notify\Type::SUGGEST) {
326                 $itemlink =  $params['link'];
327                 $subject = $l10n->t('%s Friend suggestion received', $SUBJECT_PREFIX);
328
329                 $preamble = $l10n->t('You\'ve received a friend suggestion from \'%1$s\' at %2$s', $params['source_name'], $sitename);
330                 $epreamble = $l10n->t('You\'ve received [url=%1$s]a friend suggestion[/url] for %2$s from %3$s.',
331                         $itemlink,
332                         '[url='.$params['item']['url'].']'.$params['item']['name'].'[/url]',
333                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]'
334                 );
335
336                 $body = $l10n->t('Name:').' '.$params['item']['name']."\n";
337                 $body .= $l10n->t('Photo:').' '.$params['item']['photo']."\n";
338                 $body .= $l10n->t('You may visit their profile at %s', $params['item']['url']);
339
340                 $sitelink = $l10n->t('Please visit %s to approve or reject the suggestion.');
341                 $tsitelink = sprintf($sitelink, $siteurl);
342                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
343         }
344
345         if ($params['type'] == Notify\Type::CONFIRM) {
346                 if ($params['verb'] == Activity::FRIEND) { // mutual connection
347                         $itemlink =  $params['link'];
348                         $subject = $l10n->t('%s Connection accepted', $SUBJECT_PREFIX);
349
350                         $preamble = $l10n->t('\'%1$s\' has accepted your connection request at %2$s', $params['source_name'], $sitename);
351                         $epreamble = $l10n->t('%2$s has accepted your [url=%1$s]connection request[/url].',
352                                 $itemlink,
353                                 '[url='.$params['source_link'].']'.$params['source_name'].'[/url]'
354                         );
355
356                         $body =  $l10n->t('You are now mutual friends and may exchange status updates, photos, and email without restriction.');
357
358                         $sitelink = $l10n->t('Please visit %s if you wish to make any changes to this relationship.');
359                         $tsitelink = sprintf($sitelink, $siteurl);
360                         $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
361                 } else { // ACTIVITY_FOLLOW
362                         $itemlink =  $params['link'];
363                         $subject = $l10n->t('%s Connection accepted', $SUBJECT_PREFIX);
364
365                         $preamble = $l10n->t('\'%1$s\' has accepted your connection request at %2$s', $params['source_name'], $sitename);
366                         $epreamble = $l10n->t('%2$s has accepted your [url=%1$s]connection request[/url].',
367                                 $itemlink,
368                                 '[url='.$params['source_link'].']'.$params['source_name'].'[/url]'
369                         );
370
371                         $body =  $l10n->t('\'%1$s\' has chosen to accept you a fan, which restricts some forms of communication - such as private messaging and some profile interactions. If this is a celebrity or community page, these settings were applied automatically.', $params['source_name']);
372                         $body .= "\n\n";
373                         $body .= $l10n->t('\'%1$s\' may choose to extend this into a two-way or more permissive relationship in the future.', $params['source_name']);
374
375                         $sitelink = $l10n->t('Please visit %s  if you wish to make any changes to this relationship.');
376                         $tsitelink = sprintf($sitelink, $siteurl);
377                         $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
378                 }
379         }
380
381         if ($params['type'] == Notify\Type::SYSTEM) {
382                 switch($params['event']) {
383                         case "SYSTEM_REGISTER_REQUEST":
384                                 $itemlink =  $params['link'];
385                                 $subject = $l10n->t('[Friendica System Notify]') . ' ' . $l10n->t('registration request');
386
387                                 $preamble = $l10n->t('You\'ve received a registration request from \'%1$s\' at %2$s', $params['source_name'], $sitename);
388                                 $epreamble = $l10n->t('You\'ve received a [url=%1$s]registration request[/url] from %2$s.',
389                                         $itemlink,
390                                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]'
391                                 );
392
393                                 $body = $l10n->t("Full Name:    %s\nSite Location:      %s\nLogin Name: %s (%s)",
394                                         $params['source_name'],
395                                         $siteurl, $params['source_mail'],
396                                         $params['source_nick']
397                                 );
398
399                                 $sitelink = $l10n->t('Please visit %s to approve or reject the request.');
400                                 $tsitelink = sprintf($sitelink, $params['link']);
401                                 $hsitelink = sprintf($sitelink, '<a href="'.$params['link'].'">'.$sitename.'</a><br><br>');
402                                 break;
403                         case "SYSTEM_DB_UPDATE_FAIL":
404                                 break;
405                 }
406         }
407
408         $subject .= " (".$nickname."@".$hostname.")";
409
410         $h = [
411                 'params'    => $params,
412                 'subject'   => $subject,
413                 'preamble'  => $preamble,
414                 'epreamble' => $epreamble,
415                 'body'      => $body,
416                 'sitelink'  => $sitelink,
417                 'tsitelink' => $tsitelink,
418                 'hsitelink' => $hsitelink,
419                 'itemlink'  => $itemlink
420         ];
421
422         Hook::callAll('enotify', $h);
423
424         $subject   = $h['subject'];
425
426         $preamble  = $h['preamble'];
427         $epreamble = $h['epreamble'];
428
429         $body      = $h['body'];
430
431         $tsitelink = $h['tsitelink'];
432         $hsitelink = $h['hsitelink'];
433         $itemlink  = $h['itemlink'];
434
435         $notify_id = 0;
436
437         if ($show_in_notification_page) {
438                 $notification = DI::notify()->insert([
439                         'name'       => $params['source_name'] ?? '',
440                         'name_cache' => strip_tags(BBCode::convert($params['source_name'] ?? '')),
441                         'url'        => $params['source_link'] ?? '',
442                         'photo'      => $params['source_photo'] ?? '',
443                         'link'       => $itemlink ?? '',
444                         'uid'        => $params['uid'] ?? 0,
445                         'iid'        => $item_id ?? 0,
446                         'parent'     => $parent_id ?? 0,
447                         'type'       => $params['type'] ?? '',
448                         'verb'       => $params['verb'] ?? '',
449                         'otype'      => $params['otype'] ?? '',
450                 ]);
451
452                 $notification->msg = Renderer::replaceMacros($epreamble, ['$itemlink' => $notification->link]);
453
454                 DI::notify()->update($notification);
455
456                 $itemlink  = DI::baseUrl() . '/notification/' . $notification->id;
457                 $notify_id = $notification->id;
458         }
459
460         // send email notification if notification preferences permit
461         if ((intval($params['notify_flags']) & intval($params['type']))
462                 || $params['type'] == Notify\Type::SYSTEM) {
463
464                 Logger::log('sending notification email');
465
466                 if (isset($params['parent']) && (intval($params['parent']) != 0)) {
467                         $id_for_parent = $params['parent'] . "@" . $hostname;
468
469                         // Is this the first email notification for this parent item and user?
470                         if (!DBA::exists('notify-threads', ['master-parent-item' => $params['parent'], 'receiver-uid' => $params['uid']])) {
471                                 Logger::log("notify_id:" . intval($notify_id) . ", parent: " . intval($params['parent']) . "uid: " . intval($params['uid']), Logger::DEBUG);
472
473                                 $fields = ['notify-id'    => $notify_id, 'master-parent-item' => $params['parent'],
474                                            'receiver-uid' => $params['uid'], 'parent-item' => 0];
475                                 DBA::insert('notify-threads', $fields);
476
477                                 $additional_mail_header .= "Message-ID: <${id_for_parent}>\n";
478                                 $log_msg                = "include/enotify: No previous notification found for this parent:\n" .
479                                                           "  parent: ${params['parent']}\n" . "  uid   : ${params['uid']}\n";
480                                 Logger::log($log_msg, Logger::DEBUG);
481                         } else {
482                                 // If not, just "follow" the thread.
483                                 $additional_mail_header .= "References: <${id_for_parent}>\nIn-Reply-To: <${id_for_parent}>\n";
484                                 Logger::log("There's already a notification for this parent.", Logger::DEBUG);
485                         }
486                 }
487
488                 $datarray = [
489                         'preamble'     => $preamble,
490                         'type'         => $params['type'],
491                         'parent'       => $parent_id,
492                         'source_name'  => $params['source_name'] ?? null,
493                         'source_link'  => $params['source_link'] ?? null,
494                         'source_photo' => $params['source_photo'] ?? null,
495                         'uid'          => $params['uid'],
496                         'hsitelink'    => $hsitelink,
497                         'tsitelink'    => $tsitelink,
498                         'itemlink'     => $itemlink,
499                         'title'        => $title,
500                         'body'         => $body,
501                         'subject'      => $subject,
502                         'headers'      => $additional_mail_header,
503                 ];
504
505                 Hook::callAll('enotify_mail', $datarray);
506
507                 $builder = DI::emailer()
508                         ->newNotifyMail()
509                         ->addHeaders($datarray['headers'])
510                         ->withRecipient($params['to_email'])
511                         ->forUser([
512                                 'uid' => $datarray['uid'],
513                                 'language' => $params['language'],
514                         ])
515                         ->withNotification($datarray['subject'], $datarray['preamble'], $datarray['title'], $datarray['body'])
516                         ->withSiteLink($datarray['tsitelink'], $datarray['hsitelink'])
517                         ->withItemLink($datarray['itemlink']);
518
519                 // If a photo is present, add it to the email
520                 if (!empty($datarray['source_photo'])) {
521                         $builder->withPhoto(
522                                 $datarray['source_photo'],
523                                 $datarray['source_link'] ?? $sitelink,
524                                 $datarray['source_name'] ?? $sitename);
525                 }
526
527                 $email = $builder->build();
528
529                 // use the Emailer class to send the message
530                 return DI::emailer()->send($email);
531         }
532
533         return false;
534 }
535
536 /**
537  * Checks for users who should be notified
538  *
539  * @param int $itemid ID of the item for which the check should be done
540  * @throws \Friendica\Network\HTTPException\InternalServerErrorException
541  */
542 function check_user_notification($itemid) {
543         // fetch all users with notifications
544         $useritems = DBA::select('user-item', ['uid', 'notification-type'], ['iid' => $itemid]);
545         while ($useritem = DBA::fetch($useritems)) {
546                 check_item_notification($itemid, $useritem['uid'], $useritem['notification-type']);
547         }
548         DBA::close($useritems);
549 }
550
551 /**
552  * Checks for item related notifications and sends them
553  *
554  * @param int    $itemid            ID of the item for which the check should be done
555  * @param int    $uid               User ID
556  * @param int    $notification_type Notification bits
557  * @return bool
558  * @throws \Friendica\Network\HTTPException\InternalServerErrorException
559  */
560 function check_item_notification($itemid, $uid, $notification_type) {
561         $fields = ['id', 'mention', 'tag', 'parent', 'title', 'body',
562                 'author-link', 'author-name', 'author-avatar', 'author-id',
563                 'guid', 'parent-uri', 'uri', 'contact-id', 'network'];
564         $condition = ['id' => $itemid, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT], 'deleted' => false];
565         $item = Item::selectFirstForUser($uid, $fields, $condition);
566         if (!DBA::isResult($item)) {
567                 return false;
568         }
569
570         // Generate the notification array
571         $params = [];
572         $params['uid'] = $uid;
573         $params['item'] = $item;
574         $params['parent'] = $item['parent'];
575         $params['link'] = DI::baseUrl() . '/display/' . urlencode($item['guid']);
576         $params['otype'] = 'item';
577         $params['source_name'] = $item['author-name'];
578         $params['source_link'] = $item['author-link'];
579         $params['source_photo'] = $item['author-avatar'];
580
581         // Set the activity flags
582         $params['activity']['explicit_tagged'] = ($notification_type & UserItem::NOTIF_EXPLICIT_TAGGED);
583         $params['activity']['implicit_tagged'] = ($notification_type & UserItem::NOTIF_IMPLICIT_TAGGED);
584         $params['activity']['origin_comment'] = ($notification_type & UserItem::NOTIF_DIRECT_COMMENT);
585         $params['activity']['origin_thread'] = ($notification_type & UserItem::NOTIF_THREAD_COMMENT);
586         $params['activity']['thread_comment'] = ($notification_type & UserItem::NOTIF_COMMENT_PARTICIPATION);
587         $params['activity']['thread_activity'] = ($notification_type & UserItem::NOTIF_ACTIVITY_PARTICIPATION);
588
589         // Tagging a user in a direct post (first comment level) means a direct comment
590         if ($params['activity']['explicit_tagged'] && ($notification_type & UserItem::NOTIF_DIRECT_THREAD_COMMENT)) {
591                 $params['activity']['origin_comment'] = true;
592         }
593
594         if ($notification_type & UserItem::NOTIF_SHARED) {
595                 $params['type'] = Notify\Type::SHARE;
596                 $params['verb'] = Activity::POST;
597         } elseif ($notification_type & UserItem::NOTIF_EXPLICIT_TAGGED) {
598                 $params['type'] = Notify\Type::TAG_SELF;
599                 $params['verb'] = Activity::TAG;
600         } elseif ($notification_type & UserItem::NOTIF_IMPLICIT_TAGGED) {
601                 $params['type'] = Notify\Type::COMMENT;
602                 $params['verb'] = Activity::POST;
603         } elseif ($notification_type & UserItem::NOTIF_THREAD_COMMENT) {
604                 $params['type'] = Notify\Type::COMMENT;
605                 $params['verb'] = Activity::POST;
606         } elseif ($notification_type & UserItem::NOTIF_DIRECT_COMMENT) {
607                 $params['type'] = Notify\Type::COMMENT;
608                 $params['verb'] = Activity::POST;
609         } elseif ($notification_type & UserItem::NOTIF_COMMENT_PARTICIPATION) {
610                 $params['type'] = Notify\Type::COMMENT;
611                 $params['verb'] = Activity::POST;
612         } elseif ($notification_type & UserItem::NOTIF_ACTIVITY_PARTICIPATION) {
613                 $params['type'] = Notify\Type::COMMENT;
614                 $params['verb'] = Activity::POST;
615         } else {
616                 return false;
617         }
618
619         notification($params);
620 }