3 * @file include/NotificationsManager.php
5 require_once('include/html2plain.php');
6 require_once("include/datetime.php");
7 require_once("include/bbcode.php");
8 require_once("include/dbm.php");
11 * @brief Read and write notifications from/to database
13 class NotificationsManager {
16 public function __construct() {
21 * @brief set some extra note properties
23 * @param array $notes array of note arrays from db
24 * @return array Copy of input array with added properties
26 * Set some extra properties to note array from db:
27 * - timestamp as int in default TZ
28 * - date_rel : relative date string
29 * - msg_html: message as html string
30 * - msg_plain: message as plain text string
32 private function _set_extra($notes) {
34 foreach($notes as $n) {
35 $local_time = datetime_convert('UTC',date_default_timezone_get(),$n['date']);
36 $n['timestamp'] = strtotime($local_time);
37 $n['date_rel'] = relative_date($n['date']);
38 $n['msg_html'] = bbcode($n['msg'], false, false, false, false);
39 $n['msg_plain'] = explode("\n",trim(html2plain($n['msg_html'], 0)))[0];
48 * @brief get all notifications for local_user()
50 * @param array $filter optional Array "column name"=>value: filter query by columns values
51 * @param string $order optional Space separated list of column to sort by. prepend name with "+" to sort ASC, "-" to sort DESC. Default to "-date"
52 * @param string $limit optional Query limits
54 * @return array of results or false on errors
56 public function getAll($filter = array(), $order="-date", $limit="") {
57 $filter_str = array();
59 foreach($filter as $column => $value) {
60 $filter_str[] = sprintf("`%s` = '%s'", $column, dbesc($value));
62 if (count($filter_str)>0) {
63 $filter_sql = "AND ".implode(" AND ", $filter_str);
66 $aOrder = explode(" ", $order);
68 foreach($aOrder as $o) {
78 $asOrder[] = "$o $dir";
80 $order_sql = implode(", ", $asOrder);
82 if ($limit!="") $limit = " LIMIT ".$limit;
84 $r = q("SELECT * FROM `notify` WHERE `uid` = %d $filter_sql ORDER BY $order_sql $limit",
87 if ($r!==false && count($r)>0) return $this->_set_extra($r);
92 * @brief get one note for local_user() by $id value
95 * @return array note values or null if not found
97 public function getByID($id) {
98 $r = q("SELECT * FROM `notify` WHERE `id` = %d AND `uid` = %d LIMIT 1",
102 if($r!==false && count($r)>0) {
103 return $this->_set_extra($r)[0];
109 * @brief set seen state of $note of local_user()
112 * @param bool $seen optional true or false, default true
113 * @return bool true on success, false on errors
115 public function setSeen($note, $seen = true) {
116 return q("UPDATE `notify` SET `seen` = %d WHERE ( `link` = '%s' OR ( `parent` != 0 AND `parent` = %d AND `otype` = '%s' )) AND `uid` = %d",
118 dbesc($note['link']),
119 intval($note['parent']),
120 dbesc($note['otype']),
126 * @brief set seen state of all notifications of local_user()
128 * @param bool $seen optional true or false. default true
129 * @return bool true on success, false on error
131 public function setAllSeen($seen = true) {
132 return q("UPDATE `notify` SET `seen` = %d WHERE `uid` = %d",
139 * @brief List of pages for the Notifications TabBar
142 * @return array with with notifications TabBar data
144 public function getTabs() {
147 'label' => t('System'),
148 'url'=>'notifications/system',
149 'sel'=> (($this->a->argv[1] == 'system') ? 'active' : ''),
150 'id' => 'system-tab',
154 'label' => t('Network'),
155 'url'=>'notifications/network',
156 'sel'=> (($this->a->argv[1] == 'network') ? 'active' : ''),
157 'id' => 'network-tab',
161 'label' => t('Personal'),
162 'url'=>'notifications/personal',
163 'sel'=> (($this->a->argv[1] == 'personal') ? 'active' : ''),
164 'id' => 'personal-tab',
168 'label' => t('Home'),
169 'url' => 'notifications/home',
170 'sel'=> (($this->a->argv[1] == 'home') ? 'active' : ''),
175 'label' => t('Introductions'),
176 'url' => 'notifications/intros',
177 'sel'=> (($this->a->argv[1] == 'intros') ? 'active' : ''),
186 public function format($notifs, $ident = "") {
191 if (dbm::is_result($notifs)) {
193 foreach ($notifs as $it) {
195 $it['seen'] = ($it['unseen'] > 0 ? false : true);
199 $default_item_label = 'notify';
200 $default_item_link = app::get_baseurl(true).'/notify/view/'. $it['id'];
201 $default_item_image = proxy_url($it['photo'], false, PROXY_SIZE_MICRO);
202 $default_item_text = strip_tags(bbcode($it['msg']));
203 $default_item_when = relative_date($it['date']);
204 $default_tpl = $tpl_notify;
208 $default_item_label = 'comment';
209 $default_item_link = app::get_baseurl(true).'/display/'.$it['pguid'];
210 $default_item_image = proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO);
211 $default_item_text = sprintf( t("%s commented on %s's post"), $it['author-name'], $it['pname']);
212 $default_item_when = relative_date($it['created']);
213 $default_tpl = $tpl_item_comments;
217 $default_item_label = (($it['id'] == $it['parent']) ? 'post' : 'comment');
218 $default_item_link = app::get_baseurl(true).'/display/'.$it['pguid'];
219 $default_item_image = proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO);
220 $default_item_text = (($it['id'] == $it['parent'])
221 ? sprintf( t("%s created a new post"), $it['author-name'])
222 : sprintf( t("%s commented on %s's post"), $it['author-name'], $it['pname']));
223 $default_item_when = relative_date($it['created']);
224 $default_tpl = (($it['id'] == $it['parent']) ? $tpl_item_posts : $tpl_item_comments);
231 //'$item_link' => $a->get_baseurl(true).'/display/'.$a->user['nickname']."/".$it['parent'],
233 'link' => app::get_baseurl(true).'/display/'.$it['pguid'],
234 '$image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
235 'text' => sprintf( t("%s liked %s's post"), $it['author-name'], $it['pname']),
236 'when' => relative_date($it['created']),
237 'seen' => $it['seen']
241 case ACTIVITY_DISLIKE:
243 //'$item_link' => $a->get_baseurl(true).'/display/'.$a->user['nickname']."/".$it['parent'],
244 'label' => 'dislike',
245 'link' => app::get_baseurl(true).'/display/'.$it['pguid'],
246 'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
247 'text' => sprintf( t("%s disliked %s's post"), $it['author-name'], $it['pname']),
248 'when' => relative_date($it['created']),
249 'seen' => $it['seen']
253 case ACTIVITY_FRIEND:
254 $xmlhead="<"."?xml version='1.0' encoding='UTF-8' ?".">";
255 $obj = parse_xml_string($xmlhead.$it['object']);
256 $it['fname'] = $obj->title;
259 //'$item_link' => $a->get_baseurl(true).'/display/'.$a->user['nickname']."/".$it['parent'],
261 'link' => app::get_baseurl(true).'/display/'.$it['pguid'],
262 'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
263 'text' => sprintf( t("%s is now friends with %s"), $it['author-name'], $it['fname']),
264 'when' => relative_date($it['created']),
265 'seen' => $it['seen']
271 //'$item_link' => $a->get_baseurl(true).'/display/'.$a->user['nickname']."/".$it['parent'],
272 'label' => $default_item_label,
273 'link' => $default_item_link,
274 'image' => $default_item_image,
275 'text' => $default_item_text,
276 'when' => $default_item_when,
277 'seen' => $it['seen']
289 private function networkTotal($seen = 0) {
291 $sql_seen = " AND `item`.`unseen` = 1 ";
293 $r = q("SELECT COUNT(*) AS `total`
294 FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent`
295 WHERE `item`.`visible` = 1 AND `pitem`.`parent` != 0 AND
296 `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0
301 if(dbm::is_result($r))
302 return $r[0]['total'];
307 public function networkNotifs($seen = 0) {
309 $total = $this->networkTotal($seen);
312 $sql_seen = " AND `item`.`unseen` = 1 ";
315 $r = q("SELECT `item`.`id`,`item`.`parent`, `item`.`verb`, `item`.`author-name`, `item`.`unseen`,
316 `item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object` AS `object`,
317 `pitem`.`author-name` AS `pname`, `pitem`.`author-link` AS `plink`, `pitem`.`guid` AS `pguid`
318 FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent`
319 WHERE `item`.`visible` = 1 AND `pitem`.`parent` != 0 AND
320 `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0
322 ORDER BY `item`.`created` DESC",
326 if(dbm::is_result($r)) {
327 $notifs = $this->format($r, $ident);
329 'notifications' => $notifs,
338 private function systemTotal($seen = 0) {
340 $sql_seen = " AND `seen` = 0 ";
342 $r = q("SELECT COUNT(*) AS `total` FROM `notify` WHERE `uid` = %d $sql_seen",
346 if(dbm::is_result($r))
347 return $r[0]['total'];
352 public function systemNotifs($seen = 0) {
354 $total = $this->systemTotal($seen);
357 $sql_seen = " AND `seen` = 0 ";
359 $r = q("SELECT * FROM `notify` WHERE `uid` = %d $sql_seen ORDER BY `date` DESC",
363 if(dbm::is_result($r)) {
364 $notifs = $this->format($r, $ident);
366 'notifications' => $notifs,
375 private function _personal_sql_extra() {
376 $myurl = app::get_baseurl(true) . '/profile/'. $this->a->user['nickname'];
377 $myurl = substr($myurl,strpos($myurl,'://')+3);
378 $myurl = str_replace(array('www.','.'),array('','\\.'),$myurl);
379 $diasp_url = str_replace('/profile/','/u/',$myurl);
380 $sql_extra .= sprintf(" AND ( `item`.`author-link` regexp '%s' or `item`.`tag` regexp '%s' or `item`.`tag` regexp '%s' ) ",
382 dbesc($myurl . '\\]'),
383 dbesc($diasp_url . '\\]')
389 private function personalTotal($seen = 0) {
390 $sql_extra .= $this->_personal_sql_extra();
393 $sql_seen = " AND `item`.`unseen` = 1 ";
395 $r = q("SELECT COUNT(*) AS `total`
396 FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent`
397 WHERE `item`.`visible` = 1
400 AND `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0 " ,
404 if(dbm::is_result($r))
405 return $r[0]['total'];
409 public function personalNotifs($seen = 0) {
412 $sql_extra .= $this->_personal_sql_extra();
415 $sql_seen = " AND `item`.`unseen` = 1 ";
417 $r = q("SELECT `item`.`id`,`item`.`parent`, `item`.`verb`, `item`.`author-name`, `item`.`unseen`,
418 `item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object` AS `object`,
419 `pitem`.`author-name` AS `pname`, `pitem`.`author-link` AS `plink`, `pitem`.`guid` AS `pguid`,
420 FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent`
421 WHERE `item`.`visible` = 1
424 AND `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0
425 ORDER BY `item`.`created` DESC" ,
429 if(dbm::is_result($r)) {
430 $notifs = $this->format($r, $ident);
432 'notifications' => $notifs,
441 private function homeTotal($seen = 0) {
443 $sql_seen = " AND `item`.`unseen` = 1 ";
445 $r = q("SELECT COUNT(*) AS `total` FROM `item`
446 WHERE ``item`.`visible` = 1 AND
447 `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 1
452 if(dbm::is_result($r))
458 public function homeNotifs($seen = 0) {
460 $total = $this->homeTotal($seen);
463 $sql_seen = " AND `item`.`unseen` = 1 ";
465 $total = $this->homeTotal($seen);
467 $r = q("SELECT `item`.`id`,`item`.`parent`, `item`.`verb`, `item`.`author-name`, `item`.`unseen`,
468 `item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object` as `object`,
469 `pitem`.`author-name` as `pname`, `pitem`.`author-link` as `plink`, `pitem`.`guid` as `pguid`
470 FROM `item` INNER JOIN `item` as `pitem` ON `pitem`.`id`=`item`.`parent`
471 WHERE `item`.`visible` = 1 AND
472 `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 1
474 ORDER BY `item`.`created` DESC",
478 if(dbm::is_result($r)) {
479 $notifs = $this->format($r, $ident);
481 'notifications' => $notifs,