]> git.mxchange.org Git - friendica.git/blob - include/enotify.php
Merge remote-tracking branch 'upstream/develop' into 1705-some-more-dba
[friendica.git] / include / enotify.php
1 <?php
2
3 use Friendica\App;
4
5 require_once('include/Emailer.php');
6 require_once('include/email.php');
7 require_once('include/bbcode.php');
8 require_once('include/html2bbcode.php');
9
10 /**
11  * @brief Creates a notification entry and possibly sends a mail
12  *
13  * @param array $params Array with the elements:
14                         uid, item, parent, type, otype, verb, event,
15                         link, subject, body, to_name, to_email, source_name,
16                         source_link, activity, preamble, notify_flags,
17                         language, show_in_notification_page
18  */
19 function notification($params) {
20
21         $a = get_app();
22
23         // from here on everything is in the recipients language
24
25         push_lang($params['language']);
26
27         $banner = t('Friendica Notification');
28         $product = FRIENDICA_PLATFORM;
29         $siteurl = App::get_baseurl(true);
30         $thanks = t('Thank You,');
31         $sitename = $a->config['sitename'];
32         if (!x($a->config['admin_name']))
33             $site_admin = sprintf(t('%s Administrator'), $sitename);
34         else
35             $site_admin = sprintf(t('%1$s, %2$s Administrator'), $a->config['admin_name'], $sitename);
36
37         $nickname = "";
38
39         $sender_name = $sitename;
40         $hostname = $a->get_hostname();
41         if (strpos($hostname, ':'))
42                 $hostname = substr($hostname, 0, strpos($hostname, ':'));
43
44         $sender_email = $a->config['sender_email'];
45         if (empty($sender_email))
46                 $sender_email = t('noreply').'@'.$hostname;
47
48         $user = q("SELECT `nickname` FROM `user` WHERE `uid` = %d", intval($params['uid']));
49         if ($user)
50                 $nickname = $user[0]["nickname"];
51
52         // with $params['show_in_notification_page'] == false, the notification isn't inserted into
53         // the database, and an email is sent if applicable.
54         // default, if not specified: true
55         $show_in_notification_page = ((x($params, 'show_in_notification_page')) ? $params['show_in_notification_page']:true);
56
57         $additional_mail_header = "";
58         $additional_mail_header .= "Precedence: list\n";
59         $additional_mail_header .= "X-Friendica-Host: ".$hostname."\n";
60         $additional_mail_header .= "X-Friendica-Account: <".$nickname."@".$hostname.">\n";
61         $additional_mail_header .= "X-Friendica-Platform: ".FRIENDICA_PLATFORM."\n";
62         $additional_mail_header .= "X-Friendica-Version: ".FRIENDICA_VERSION."\n";
63         $additional_mail_header .= "List-ID: <notification.".$hostname.">\n";
64         $additional_mail_header .= "List-Archive: <".App::get_baseurl()."/notifications/system>\n";
65
66         if (array_key_exists('item', $params)) {
67                 $title = $params['item']['title'];
68                 $body = $params['item']['body'];
69         } else
70                 $title = $body = '';
71
72         // e.g. "your post", "David's photo", etc.
73         $possess_desc = t('%s <!item_type!>');
74
75         if (isset($params['item']['id']))
76                 $item_id = $params['item']['id'];
77         else
78                 $item_id = 0;
79
80         if (isset($params['parent']))
81                 $parent_id = $params['parent'];
82         else
83                 $parent_id = 0;
84
85         if ($params['type'] == NOTIFY_MAIL) {
86                 $subject = sprintf(t('[Friendica:Notify] New mail received at %s'), $sitename);
87
88                 $preamble = sprintf(t('%1$s sent you a new private message at %2$s.'), $params['source_name'], $sitename);
89                 $epreamble = sprintf(t('%1$s sent you %2$s.'), '[url='.$params['source_link'].']'.$params['source_name'].'[/url]', '[url=$itemlink]'.t('a private message').'[/url]');
90
91                 $sitelink = t('Please visit %s to view and/or reply to your private messages.');
92                 $tsitelink = sprintf($sitelink, $siteurl.'/message/'.$params['item']['id']);
93                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'/message/'.$params['item']['id'].'">'.$sitename.'</a>');
94                 $itemlink = $siteurl.'/message/'.$params['item']['id'];
95         }
96
97         if ($params['type'] == NOTIFY_COMMENT) {
98                 $p = q("SELECT `ignored` FROM `thread` WHERE `iid` = %d AND `uid` = %d LIMIT 1",
99                         intval($parent_id),
100                         intval($params['uid'])
101                 );
102                 if ($p AND count($p) AND ($p[0]["ignored"])) {
103                         logger("Thread ".$parent_id." will be ignored", LOGGER_DEBUG);
104                         return;
105                 }
106
107                 // Check to see if there was already a tag notify or comment notify for this post.
108                 // If so don't create a second notification
109
110                 $p = null;
111                 $p = q("SELECT `id` FROM `notify` WHERE `type` IN (%d, %d, %d) AND `link` = '%s' AND `uid` = %d LIMIT 1",
112                         intval(NOTIFY_TAGSELF),
113                         intval(NOTIFY_COMMENT),
114                         intval(NOTIFY_SHARE),
115                         dbesc($params['link']),
116                         intval($params['uid'])
117                 );
118                 if ($p and count($p)) {
119                         pop_lang();
120                         return;
121                 }
122
123                 // if it's a post figure out who's post it is.
124
125                 $p = null;
126
127                 if ($params['otype'] === 'item' && $parent_id) {
128                         $p = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
129                                 intval($parent_id),
130                                 intval($params['uid'])
131                         );
132                 }
133
134                 $item_post_type = item_post_type($p[0]);
135
136                 // "a post"
137                 $dest_str = sprintf(t('%1$s commented on [url=%2$s]a %3$s[/url]'),
138                                                                 '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
139                                                                 $itemlink,
140                                                                 $item_post_type);
141
142                 // "George Bull's post"
143                 if ($p)
144                         $dest_str = sprintf(t('%1$s commented on [url=%2$s]%3$s\'s %4$s[/url]'),
145                                                 '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
146                                                 $itemlink,
147                                                 $p[0]['author-name'],
148                                                 $item_post_type);
149
150                 // "your post"
151                 if ($p[0]['owner-name'] == $p[0]['author-name'] && $p[0]['wall'])
152                         $dest_str = sprintf(t('%1$s commented on [url=%2$s]your %3$s[/url]'),
153                                                                 '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
154                                                                 $itemlink,
155                                                                 $item_post_type);
156
157                 // Some mail softwares relies on subject field for threading.
158                 // So, we cannot have different subjects for notifications of the same thread.
159                 // Before this we have the name of the replier on the subject rendering
160                 // differents subjects for messages on the same thread.
161
162                 $subject = sprintf(t('[Friendica:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $params['source_name']);
163
164                 $preamble = sprintf(t('%s commented on an item/conversation you have been following.'), $params['source_name']);
165                 $epreamble = $dest_str;
166
167                 $sitelink = t('Please visit %s to view and/or reply to the conversation.');
168                 $tsitelink = sprintf($sitelink, $siteurl);
169                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
170                 $itemlink =  $params['link'];
171         }
172
173         if ($params['type'] == NOTIFY_WALL) {
174                 $subject = sprintf(t('[Friendica:Notify] %s posted to your profile wall'), $params['source_name']);
175
176                 $preamble = sprintf(t('%1$s posted to your profile wall at %2$s'), $params['source_name'], $sitename);
177                 $epreamble = sprintf(t('%1$s posted to [url=%2$s]your wall[/url]'),
178                                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
179                                         $params['link']);
180
181                 $sitelink = t('Please visit %s to view and/or reply to the conversation.');
182                 $tsitelink = sprintf($sitelink, $siteurl);
183                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
184                 $itemlink =  $params['link'];
185         }
186
187         if ($params['type'] == NOTIFY_TAGSELF) {
188                 $subject = sprintf(t('[Friendica:Notify] %s tagged you'), $params['source_name']);
189
190                 $preamble = sprintf(t('%1$s tagged you at %2$s'), $params['source_name'], $sitename);
191                 $epreamble = sprintf(t('%1$s [url=%2$s]tagged you[/url].'),
192                                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
193                                         $params['link']);
194
195                 $sitelink = t('Please visit %s to view and/or reply to the conversation.');
196                 $tsitelink = sprintf($sitelink, $siteurl);
197                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
198                 $itemlink =  $params['link'];
199         }
200
201         if ($params['type'] == NOTIFY_SHARE) {
202                 $subject = sprintf(t('[Friendica:Notify] %s shared a new post'), $params['source_name']);
203
204                 $preamble = sprintf(t('%1$s shared a new post at %2$s'), $params['source_name'], $sitename);
205                 $epreamble = sprintf(t('%1$s [url=%2$s]shared a post[/url].'),
206                                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
207                                         $params['link']);
208
209                 $sitelink = t('Please visit %s to view and/or reply to the conversation.');
210                 $tsitelink = sprintf($sitelink, $siteurl);
211                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
212                 $itemlink =  $params['link'];
213         }
214
215         if ($params['type'] == NOTIFY_POKE) {
216                 $subject = sprintf(t('[Friendica:Notify] %1$s poked you'), $params['source_name']);
217
218                 $preamble = sprintf(t('%1$s poked you at %2$s'), $params['source_name'], $sitename);
219                 $epreamble = sprintf(t('%1$s [url=%2$s]poked you[/url].'),
220                                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
221                                         $params['link']);
222
223                 $subject = str_replace('poked', t($params['activity']), $subject);
224                 $preamble = str_replace('poked', t($params['activity']), $preamble);
225                 $epreamble = str_replace('poked', t($params['activity']), $epreamble);
226
227                 $sitelink = 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_TAGSHARE) {
234                 $subject = sprintf(t('[Friendica:Notify] %s tagged your post'), $params['source_name']);
235
236                 $preamble = sprintf(t('%1$s tagged your post at %2$s'), $params['source_name'], $sitename);
237                 $epreamble = sprintf(t('%1$s tagged [url=%2$s]your post[/url]'),
238                                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
239                                         $itemlink);
240
241                 $sitelink = t('Please visit %s to view and/or reply to the conversation.');
242                 $tsitelink = sprintf($sitelink, $siteurl);
243                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
244                 $itemlink =  $params['link'];
245         }
246
247         if ($params['type'] == NOTIFY_INTRO) {
248                 $subject = sprintf(t('[Friendica:Notify] Introduction received'));
249
250                 $preamble = sprintf(t('You\'ve received an introduction from \'%1$s\' at %2$s'), $params['source_name'], $sitename);
251                 $epreamble = sprintf(t('You\'ve received [url=%1$s]an introduction[/url] from %2$s.'),
252                                         $itemlink,
253                                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]');
254
255                 $body = sprintf(t('You may visit their profile at %s'), $params['source_link']);
256
257                 $sitelink = t('Please visit %s to approve or reject the introduction.');
258                 $tsitelink = sprintf($sitelink, $siteurl);
259                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
260                 $itemlink =  $params['link'];
261
262                 switch ($params['verb']) {
263                         case ACTIVITY_FRIEND:
264                                 // someone started to share with user (mostly OStatus)
265                                 $subject = sprintf(t('[Friendica:Notify] A new person is sharing with you'));
266
267                                 $preamble = sprintf(t('%1$s is sharing with you at %2$s'), $params['source_name'], $sitename);
268                                 $epreamble = sprintf(t('%1$s is sharing with you at %2$s'),
269                                                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
270                                                         $sitename);
271                                 break;
272                         case ACTIVITY_FOLLOW:
273                                 // someone started to follow the user (mostly OStatus)
274                                 $subject = sprintf(t('[Friendica:Notify] You have a new follower'));
275
276                                 $preamble = sprintf(t('You have a new follower at %2$s : %1$s'), $params['source_name'], $sitename);
277                                 $epreamble = sprintf(t('You have a new follower at %2$s : %1$s'),
278                                                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
279                                                         $sitename);
280                                 break;
281                         default:
282                                 // ACTIVITY_REQ_FRIEND is default activity for notifications
283                                 break;
284                 }
285         }
286
287         if ($params['type'] == NOTIFY_SUGGEST) {
288                 $subject = sprintf(t('[Friendica:Notify] Friend suggestion received'));
289
290                 $preamble = sprintf(t('You\'ve received a friend suggestion from \'%1$s\' at %2$s'), $params['source_name'], $sitename);
291                 $epreamble = sprintf(t('You\'ve received [url=%1$s]a friend suggestion[/url] for %2$s from %3$s.'),
292                                         $itemlink,
293                                         '[url='.$params['item']['url'].']'.$params['item']['name'].'[/url]',
294                                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]');
295
296                 $body = t('Name:').' '.$params['item']['name']."\n";
297                 $body .= t('Photo:').' '.$params['item']['photo']."\n";
298                 $body .= sprintf(t('You may visit their profile at %s'), $params['item']['url']);
299
300                 $sitelink = t('Please visit %s to approve or reject the suggestion.');
301                 $tsitelink = sprintf($sitelink, $siteurl);
302                 $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
303                 $itemlink =  $params['link'];
304         }
305
306         if ($params['type'] == NOTIFY_CONFIRM) {
307                 if ($params['verb'] == ACTIVITY_FRIEND) { // mutual connection
308                         $subject = sprintf(t('[Friendica:Notify] Connection accepted'));
309
310                         $preamble = sprintf(t('\'%1$s\' has accepted your connection request at %2$s'), $params['source_name'], $sitename);
311                         $epreamble = sprintf(t('%2$s has accepted your [url=%1$s]connection request[/url].'),
312                                                 $itemlink,
313                                                 '[url='.$params['source_link'].']'.$params['source_name'].'[/url]');
314
315                         $body =  t('You are now mutual friends and may exchange status updates, photos, and email without restriction.');
316
317                         $sitelink = t('Please visit %s if you wish to make any changes to this relationship.');
318                         $tsitelink = sprintf($sitelink, $siteurl);
319                         $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
320                         $itemlink =  $params['link'];
321                 } else { // ACTIVITY_FOLLOW
322                         $subject = sprintf(t('[Friendica:Notify] Connection accepted'));
323
324                         $preamble = sprintf(t('\'%1$s\' has accepted your connection request at %2$s'), $params['source_name'], $sitename);
325                         $epreamble = sprintf(t('%2$s has accepted your [url=%1$s]connection request[/url].'),
326                                                 $itemlink,
327                                                 '[url='.$params['source_link'].']'.$params['source_name'].'[/url]');
328
329                         $body =  sprintf(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']);
330                         $body .= "\n\n";
331                         $body .= sprintf(t('\'%1$s\' may choose to extend this into a two-way or more permissive relationship in the future.'), $params['source_name']);
332
333                         $sitelink = t('Please visit %s  if you wish to make any changes to this relationship.');
334                         $tsitelink = sprintf($sitelink, $siteurl);
335                         $hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
336                         $itemlink =  $params['link'];
337                 }
338         }
339
340         if ($params['type'] == NOTIFY_SYSTEM) {
341                 switch($params['event']) {
342                         case "SYSTEM_REGISTER_REQUEST":
343                                 $subject = sprintf(t('[Friendica System:Notify] registration request'));
344
345                                 $preamble = sprintf(t('You\'ve received a registration request from \'%1$s\' at %2$s'), $params['source_name'], $sitename);
346                                 $epreamble = sprintf(t('You\'ve received a [url=%1$s]registration request[/url] from %2$s.'),
347                                                         $itemlink,
348                                                         '[url='.$params['source_link'].']'.$params['source_name'].'[/url]');
349
350                                 $body = sprintf(t('Full Name:   %1$s\nSite Location:    %2$s\nLogin Name:       %3$s (%4$s)'),
351                                                                         $params['source_name'], $siteurl, $params['source_mail'], $params['source_nick']);
352
353                                 $sitelink = t('Please visit %s to approve or reject the request.');
354                                 $tsitelink = sprintf($sitelink, $params['link']);
355                                 $hsitelink = sprintf($sitelink, '<a href="'.$params['link'].'">'.$sitename.'</a><br><br>');
356                                 $itemlink =  $params['link'];
357                                 break;
358                         case "SYSTEM_DB_UPDATE_FAIL":
359                                 break;
360                 }
361         }
362
363         if ($params['type'] == "SYSTEM_EMAIL") {
364                 // not part of the notifications.
365                 // it just send a mail to the user.
366                 // It will be used by the system to send emails to users (like
367                 // password reset, invitations and so) using one look (but without
368                 // add a notification to the user, with could be inexistent)
369                 $subject = $params['subject'];
370
371                 $preamble = $params['preamble'];
372
373                 $body =  $params['body'];
374
375                 $sitelink = "";
376                 $tsitelink = "";
377                 $hsitelink = "";
378                 $itemlink =  "";
379                 $show_in_notification_page = false;
380         }
381
382         $subject .= " (".$nickname."@".$hostname.")";
383
384         $h = array(
385                 'params'    => $params,
386                 'subject'   => $subject,
387                 'preamble'  => $preamble,
388                 'epreamble' => $epreamble,
389                 'body'      => $body,
390                 'sitelink'  => $sitelink,
391                 'tsitelink' => $tsitelink,
392                 'hsitelink' => $hsitelink,
393                 'itemlink'  => $itemlink
394         );
395
396         call_hooks('enotify', $h);
397
398         $subject   = $h['subject'];
399
400         $preamble  = $h['preamble'];
401         $epreamble = $h['epreamble'];
402
403         $body      = $h['body'];
404
405         $sitelink  = $h['sitelink'];
406         $tsitelink = $h['tsitelink'];
407         $hsitelink = $h['hsitelink'];
408         $itemlink  = $h['itemlink'];
409
410         if ($show_in_notification_page) {
411                 logger("adding notification entry", LOGGER_DEBUG);
412                 do {
413                         $dups = false;
414                         $hash = random_string();
415                         $r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' LIMIT 1",
416                                 dbesc($hash));
417                         if (dbm::is_result($r)) {
418                                 $dups = true;
419                         }
420                 } while ($dups == true);
421
422                 /// @TODO One statement is enough
423                 $datarray = array();
424                 $datarray['hash']  = $hash;
425                 $datarray['name']  = $params['source_name'];
426                 $datarray['name_cache'] = strip_tags(bbcode($params['source_name']));
427                 $datarray['url']   = $params['source_link'];
428                 $datarray['photo'] = $params['source_photo'];
429                 $datarray['date']  = datetime_convert();
430                 $datarray['uid']   = $params['uid'];
431                 $datarray['link']  = $itemlink;
432                 $datarray['iid']   = $item_id;
433                 $datarray['parent'] = $parent_id;
434                 $datarray['type']  = $params['type'];
435                 $datarray['verb']  = $params['verb'];
436                 $datarray['otype'] = $params['otype'];
437                 $datarray['abort'] = false;
438
439                 call_hooks('enotify_store', $datarray);
440
441                 if ($datarray['abort']) {
442                         pop_lang();
443                         return False;
444                 }
445
446                 // create notification entry in DB
447
448                 $r = q("INSERT INTO `notify` (`hash`, `name`, `url`, `photo`, `date`, `uid`, `link`, `iid`, `parent`, `type`, `verb`, `otype`, `name_cache`)
449                         values('%s', '%s', '%s', '%s', '%s', %d, '%s', %d, %d, %d, '%s', '%s', '%s')",
450                         dbesc($datarray['hash']),
451                         dbesc($datarray['name']),
452                         dbesc($datarray['url']),
453                         dbesc($datarray['photo']),
454                         dbesc($datarray['date']),
455                         intval($datarray['uid']),
456                         dbesc($datarray['link']),
457                         intval($datarray['iid']),
458                         intval($datarray['parent']),
459                         intval($datarray['type']),
460                         dbesc($datarray['verb']),
461                         dbesc($datarray['otype']),
462                         dbesc($datarray["name_cache"])
463                 );
464
465                 $r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' AND `uid` = %d LIMIT 1",
466                         dbesc($hash),
467                         intval($params['uid'])
468                 );
469                 if ($r)
470                         $notify_id = $r[0]['id'];
471                 else {
472                         pop_lang();
473                         return False;
474                 }
475
476                 // we seem to have a lot of duplicate comment notifications due to race conditions, mostly from forums
477                 // After we've stored everything, look again to see if there are any duplicates and if so remove them
478
479                 $p = null;
480                 $p = q("SELECT `id` FROM `notify` WHERE `type` IN (%d, %d) AND `link` = '%s' AND `uid` = %d ORDER BY `id`",
481                         intval(NOTIFY_TAGSELF),
482                         intval(NOTIFY_COMMENT),
483                         dbesc($params['link']),
484                         intval($params['uid'])
485                 );
486                 if ($p && (count($p) > 1)) {
487                         for ($d = 1; $d < count($p); $d ++) {
488                                 q("DELETE FROM `notify` WHERE `id` = %d",
489                                         intval($p[$d]['id'])
490                                 );
491                         }
492
493                         // only continue on if we stored the first one
494
495                         if ($notify_id != $p[0]['id']) {
496                                 pop_lang();
497                                 return False;
498                         }
499                 }
500
501
502                 $itemlink = App::get_baseurl().'/notify/view/'.$notify_id;
503                 $msg = replace_macros($epreamble, array('$itemlink' => $itemlink));
504                 $msg_cache = format_notification_message($datarray['name_cache'], strip_tags(bbcode($msg)));
505                 $r = q("UPDATE `notify` SET `msg` = '%s', `msg_cache` = '%s' WHERE `id` = %d AND `uid` = %d",
506                         dbesc($msg),
507                         dbesc($msg_cache),
508                         intval($notify_id),
509                         intval($params['uid'])
510                 );
511         }
512
513         // send email notification if notification preferences permit
514         if ((intval($params['notify_flags']) & intval($params['type']))
515                 || $params['type'] == NOTIFY_SYSTEM
516                 || $params['type'] == "SYSTEM_EMAIL") {
517
518                 logger('sending notification email');
519
520                 if (isset($params['parent']) AND (intval($params['parent']) != 0)) {
521                         $id_for_parent = $params['parent']."@".$hostname;
522
523                         // Is this the first email notification for this parent item and user?
524
525                         $r = q("SELECT `id` FROM `notify-threads` WHERE `master-parent-item` = %d AND `receiver-uid` = %d LIMIT 1",
526                                 intval($params['parent']),
527                                 intval($params['uid']));
528
529                         // If so, create the record of it and use a message-id smtp header.
530
531                         if (!$r) {
532                                 logger("notify_id:".intval($notify_id).", parent: ".intval($params['parent'])."uid: ".intval($params['uid']), LOGGER_DEBUG);
533                                 $r = q("INSERT INTO `notify-threads` (`notify-id`, `master-parent-item`, `receiver-uid`, `parent-item`)
534                                         values(%d, %d, %d, %d)",
535                                         intval($notify_id),
536                                         intval($params['parent']),
537                                         intval($params['uid']),
538                                         0);
539
540                                 $additional_mail_header .= "Message-ID: <${id_for_parent}>\n";
541                                 $log_msg = "include/enotify: No previous notification found for this parent:\n".
542                                                 "  parent: ${params['parent']}\n"."  uid   : ${params['uid']}\n";
543                                 logger($log_msg, LOGGER_DEBUG);
544                         } else {
545                                 // If not, just "follow" the thread.
546                                 $additional_mail_header .= "References: <${id_for_parent}>\nIn-Reply-To: <${id_for_parent}>\n";
547                                 logger("There's already a notification for this parent:\n".print_r($r, true), LOGGER_DEBUG);
548                         }
549                 }
550
551                 // textversion keeps linebreaks
552                 $textversion = strip_tags(str_replace("<br>", "\n", html_entity_decode(bbcode(stripslashes(str_replace(array("\\r\\n", "\\r", "\\n"), "\n",
553                         $body))),ENT_QUOTES, 'UTF-8')));
554                 $htmlversion = html_entity_decode(bbcode(stripslashes(str_replace(array("\\r\\n", "\\r", "\\n\\n", "\\n"),
555                         "<br />\n", $body))), ENT_QUOTES, 'UTF-8');
556
557                 $datarray = array();
558                 $datarray['banner'] = $banner;
559                 $datarray['product'] = $product;
560                 $datarray['preamble'] = $preamble;
561                 $datarray['sitename'] = $sitename;
562                 $datarray['siteurl'] = $siteurl;
563                 $datarray['type'] = $params['type'];
564                 $datarray['parent'] = $params['parent'];
565                 $datarray['source_name'] = $params['source_name'];
566                 $datarray['source_link'] = $params['source_link'];
567                 $datarray['source_photo'] = $params['source_photo'];
568                 $datarray['uid'] = $params['uid'];
569                 $datarray['username'] = $params['to_name'];
570                 $datarray['hsitelink'] = $hsitelink;
571                 $datarray['tsitelink'] = $tsitelink;
572                 $datarray['hitemlink'] = '<a href="'.$itemlink.'">'.$itemlink.'</a>';
573                 $datarray['titemlink'] = $itemlink;
574                 $datarray['thanks'] = $thanks;
575                 $datarray['site_admin'] = $site_admin;
576                 $datarray['title'] = stripslashes($title);
577                 $datarray['htmlversion'] = $htmlversion;
578                 $datarray['textversion'] = $textversion;
579                 $datarray['subject'] = $subject;
580                 $datarray['headers'] = $additional_mail_header;
581
582                 call_hooks('enotify_mail', $datarray);
583
584                 // check whether sending post content in email notifications is allowed
585                 // always true for "SYSTEM_EMAIL"
586                 $content_allowed = ((!get_config('system', 'enotify_no_content')) || ($params['type'] == "SYSTEM_EMAIL"));
587
588                 // load the template for private message notifications
589                 $tpl = get_markup_template('email_notify_html.tpl');
590                 $email_html_body = replace_macros($tpl, array(
591                         '$banner'       => $datarray['banner'],
592                         '$product'      => $datarray['product'],
593                         '$preamble'     => str_replace("\n", "<br>\n", $datarray['preamble']),
594                         '$sitename'     => $datarray['sitename'],
595                         '$siteurl'      => $datarray['siteurl'],
596                         '$source_name'  => $datarray['source_name'],
597                         '$source_link'  => $datarray['source_link'],
598                         '$source_photo' => $datarray['source_photo'],
599                         '$username'     => $datarray['to_name'],
600                         '$hsitelink'    => $datarray['hsitelink'],
601                         '$hitemlink'    => $datarray['hitemlink'],
602                         '$thanks'       => $datarray['thanks'],
603                         '$site_admin'   => $datarray['site_admin'],
604                         '$title'        => $datarray['title'],
605                         '$htmlversion'  => $datarray['htmlversion'],
606                         '$content_allowed'      => $content_allowed,
607                 ));
608
609                 // load the template for private message notifications
610                 $tpl = get_markup_template('email_notify_text.tpl');
611                 $email_text_body = replace_macros($tpl, array(
612                         '$banner'       => $datarray['banner'],
613                         '$product'      => $datarray['product'],
614                         '$preamble'     => $datarray['preamble'],
615                         '$sitename'     => $datarray['sitename'],
616                         '$siteurl'      => $datarray['siteurl'],
617                         '$source_name'  => $datarray['source_name'],
618                         '$source_link'  => $datarray['source_link'],
619                         '$source_photo' => $datarray['source_photo'],
620                         '$username'     => $datarray['to_name'],
621                         '$tsitelink'    => $datarray['tsitelink'],
622                         '$titemlink'    => $datarray['titemlink'],
623                         '$thanks'       => $datarray['thanks'],
624                         '$site_admin'   => $datarray['site_admin'],
625                         '$title'        => $datarray['title'],
626                         '$textversion'  => $datarray['textversion'],
627                         '$content_allowed'      => $content_allowed,
628                 ));
629
630                 // use the Emailer class to send the message
631
632                 return Emailer::send(array(
633                         'uid' => $params['uid'],
634                         'fromName' => $sender_name,
635                         'fromEmail' => $sender_email,
636                         'replyTo' => $sender_email,
637                         'toEmail' => $params['to_email'],
638                         'messageSubject' => $datarray['subject'],
639                         'htmlVersion' => $email_html_body,
640                         'textVersion' => $email_text_body,
641                         'additionalMailHeader' => $datarray['headers'],
642                 ));
643         }
644
645     return False;
646 }
647
648 /**
649  * @brief Checks for item related notifications and sends them
650  *
651  * @param int $itemid ID of the item for which the check should be done
652  * @param int $uid User ID
653  * @param str $defaulttype (Optional) Forces a notification with this type.
654  */
655 function check_item_notification($itemid, $uid, $defaulttype = "") {
656         $notification_data = array("uid" => $uid, "profiles" => array());
657         call_hooks('check_item_notification', $notification_data);
658
659         $profiles = $notification_data["profiles"];
660
661         $user = q("SELECT `notify-flags`, `language`, `username`, `email`, `nickname` FROM `user` WHERE `uid` = %d", intval($uid));
662         if (!$user)
663                 return false;
664
665         $owner = q("SELECT `id`, `url` FROM `contact` WHERE `self` AND `uid` = %d LIMIT 1", intval($uid));
666         if (!$owner)
667                 return false;
668
669         // This is our regular URL format
670         $profiles[] = $owner[0]["url"];
671
672         // Notifications from Diaspora are often with an URL in the Diaspora format
673         $profiles[] = App::get_baseurl()."/u/".$user[0]["nickname"];
674
675         $profiles2 = array();
676
677         foreach ($profiles AS $profile) {
678                 // Check for invalid profile urls. 13 should be the shortest possible profile length:
679                 // http://a.bc/d
680                 // Additionally check for invalid urls that would return the normalised value "http:"
681                 if ((strlen($profile) >= 13) AND (normalise_link($profile) != "http:")) {
682                         if (!in_array($profile, $profiles2))
683                                 $profiles2[] = $profile;
684
685                         $profile = normalise_link($profile);
686                         if (!in_array($profile, $profiles2))
687                                 $profiles2[] = $profile;
688
689                         $profile = str_replace("http://", "https://", $profile);
690                         if (!in_array($profile, $profiles2))
691                                 $profiles2[] = $profile;
692                 }
693         }
694
695         $profiles = $profiles2;
696
697         $profile_list = "";
698
699         foreach ($profiles AS $profile) {
700                 if ($profile_list != "")
701                         $profile_list .= "', '";
702
703                 $profile_list .= dbesc($profile);
704         }
705
706         $profile_list = "'".$profile_list."'";
707
708         // Only act if it is a "real" post
709         // We need the additional check for the "local_profile" because of mixed situations on connector networks
710         $item = q("SELECT `id`, `mention`, `tag`,`parent`, `title`, `body`, `author-name`, `author-link`, `author-avatar`, `guid`,
711                         `parent-uri`, `uri`, `contact-id`
712                         FROM `item` WHERE `id` = %d AND `verb` IN ('%s', '') AND `type` != 'activity' AND
713                                 NOT (`author-link` IN ($profile_list))  LIMIT 1",
714                 intval($itemid), dbesc(ACTIVITY_POST));
715         if (!$item)
716                 return false;
717
718         // Generate the notification array
719         $params = array();
720         $params["uid"] = $uid;
721         $params["notify_flags"] = $user[0]["notify-flags"];
722         $params["language"] = $user[0]["language"];
723         $params["to_name"] = $user[0]["username"];
724         $params["to_email"] = $user[0]["email"];
725         $params["item"] = $item[0];
726         $params["parent"] = $item[0]["parent"];
727         $params["link"] = App::get_baseurl().'/display/'.urlencode($item[0]["guid"]);
728         $params["otype"] = 'item';
729         $params["source_name"] = $item[0]["author-name"];
730         $params["source_link"] = $item[0]["author-link"];
731         $params["source_photo"] = $item[0]["author-avatar"];
732
733         if ($item[0]["parent-uri"] === $item[0]["uri"]) {
734                 // Send a notification for every new post?
735                 $r = q("SELECT `notify_new_posts` FROM `contact` WHERE `id` = %d AND `uid` = %d AND `notify_new_posts` LIMIT 1",
736                         intval($item[0]['contact-id']),
737                         intval($uid)
738                 );
739                 $send_notification = dbm::is_result($r);
740
741                 if (!$send_notification) {
742                         $tags = q("SELECT `url` FROM `term` WHERE `otype` = %d AND `oid` = %d AND `type` = %d AND `uid` = %d",
743                                 intval(TERM_OBJ_POST), intval($itemid), intval(TERM_MENTION), intval($uid));
744
745                         if (dbm::is_result($tags)) {
746                                 foreach ($tags AS $tag) {
747                                         $r = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND `notify_new_posts`",
748                                                 normalise_link($tag["url"]), intval($uid));
749                                         if (dbm::is_result($r))
750                                                 $send_notification = true;
751                                 }
752                         }
753                 }
754
755                 if ($send_notification) {
756                         $params["type"] = NOTIFY_SHARE;
757                         $params["verb"] = ACTIVITY_TAG;
758                 }
759         }
760
761         // Is the user mentioned in this post?
762         $tagged = false;
763
764         foreach ($profiles AS $profile) {
765                 if (strpos($item[0]["tag"], "=".$profile."]") OR strpos($item[0]["body"], "=".$profile."]"))
766                         $tagged = true;
767         }
768
769         if ($item[0]["mention"] OR $tagged OR ($defaulttype == NOTIFY_TAGSELF)) {
770                 $params["type"] = NOTIFY_TAGSELF;
771                 $params["verb"] = ACTIVITY_TAG;
772         }
773
774         // Is it a post that the user had started or where he interacted?
775         $parent = q("SELECT `thread`.`iid` FROM `thread` INNER JOIN `item` ON `item`.`parent` = `thread`.`iid`
776                         WHERE `thread`.`iid` = %d AND `thread`.`uid` = %d AND NOT `thread`.`ignored` AND
777                                 (`thread`.`mention` OR `item`.`author-link` IN ($profile_list))
778                         LIMIT 1",
779                         intval($item[0]["parent"]), intval($uid));
780
781         if ($parent AND !isset($params["type"])) {
782                 $params["type"] = NOTIFY_COMMENT;
783                 $params["verb"] = ACTIVITY_POST;
784         }
785
786         if (isset($params["type"]))
787                 notification($params);
788 }
789
790 /**
791  * @brief Formats a notification message with the notification author
792  *
793  * Replace the name with {0} but ensure to make that only once. The {0} is used
794  * later and prints the name in bold.
795  *
796  * @param string $name
797  * @param string $message
798  * @return string Formatted message
799  */
800 function format_notification_message($name, $message) {
801         if ($name != '') {
802                 $pos = strpos($message, $name);
803         } else {
804                 $pos = false;
805         }
806
807         if ($pos !== false) {
808                 $message = substr_replace($message, '{0}', $pos, strlen($name));
809         }
810
811         return $message;
812 }