diff --git a/include/NotificationsManager.php b/include/NotificationsManager.php new file mode 100644 index 0000000000..8b0ca9e13d --- /dev/null +++ b/include/NotificationsManager.php @@ -0,0 +1,113 @@ +a = get_app(); + } + + private function _set_extra($notes) { + $rets = array(); + foreach($notes as $n) { + $local_time = datetime_convert('UTC',date_default_timezone_get(),$n['date']); + $n['timestamp'] = strtotime($local_time); + $n['date_rel'] = relative_date($n['date']); + $rets[] = $n; + } + return $rets; + } + + + /** + * @brief get all notifications for local_user() + * + * @param array $filter optional Array "column name"=>value: filter query by columns values + * @param string $order optional Space separated list of column to sort by. prepend name with "+" to sort ASC, "-" to sort DESC. Default to "-date" + * @param string $limit optional Query limits + * + * @return array of results or false on errors + */ + public function getAll($filter = array(), $order="-date", $limit="") { + $filter_str = array(); + $filter_sql = ""; + foreach($filter as $column => $value) { + $filter_str[] = sprintf("`%s` = '%s'", $column, dbesc($value)); + } + if (count($filter_str)>0) { + $filter_sql = "AND ".implode(" AND ", $filter_str); + } + + $aOrder = explode(" ", $order); + $asOrder = array(); + foreach($aOrder as $o) { + $dir = "asc"; + if ($o[0]==="-") { + $dir = "desc"; + $o = substr($o,1); + } + if ($o[0]==="+") { + $dir = "asc"; + $o = substr($o,1); + } + $asOrder[] = "$o $dir"; + } + $order_sql = implode(", ", $asOrder); + + if ($limit!="") $limit = " LIMIT ".$limit; + + $r = q("SELECT * from notify where uid = %d $filter_sql order by $order_sql $limit", + intval(local_user()) + ); + if ($r!==false && count($r)>0) return $this->_set_extra($r); + return false; + } + + /** + * @brief get one note for local_user() by $id value + * + * @param int $id + * @return array note values or null if not found + */ + public function getByID($id) { + $r = q("select * from notify where id = %d and uid = %d limit 1", + intval($id), + intval(local_user()) + ); + if($r!==false && count($r)>0) { + return $this->_set_extra($r)[0]; + } + return null; + } + + /** + * @brief set seen state of $note of local_user() + * + * @param array $note + * @param bool $seen optional true or false, default true + * @return bool true on success, false on errors + */ + public function setSeen($note, $seen = true) { + return q("update notify set seen = %d where ( link = '%s' or ( parent != 0 and parent = %d and otype = '%s' )) and uid = %d", + intval($seen), + dbesc($note['link']), + intval($note['parent']), + dbesc($note['otype']), + intval(local_user()) + ); + } + + /** + * @brief set seen state of all notifications of local_user() + * + * @param bool $seen optional true or false. default true + * @return bool true on success, false on error + */ + public function setAllSeen($seen = true) { + return q("update notify set seen = %d where uid = %d", + intval($seen), + intval(local_user()) + ); + } +} diff --git a/include/api.php b/include/api.php index 4d206da28e..5acc816575 100644 --- a/include/api.php +++ b/include/api.php @@ -23,6 +23,7 @@ require_once('include/message.php'); require_once('include/group.php'); require_once('include/like.php'); + require_once('include/NotificationsManager.php'); define('API_METHOD_ANY','*'); @@ -250,7 +251,7 @@ */ function api_call(&$a){ GLOBAL $API, $called_api; - + $type="json"; if (strpos($a->query_string, ".xml")>0) $type="xml"; if (strpos($a->query_string, ".json")>0) $type="json"; @@ -680,6 +681,29 @@ } + /** + * @brief transform $data array in xml without a template + * + * @param array $data + * @return string xml string + */ + function api_array_to_xml($data, $ename="") { + $attrs=""; + $childs=""; + foreach($data as $k=>$v) { + $k=trim($k,'$'); + if (!is_array($v)) { + $attrs .= sprintf('%s="%s" ', $k, $v); + } else { + if (is_numeric($k)) $k=trim($ename,'s'); + $childs.=api_array_to_xml($v, $k); + } + } + $res = $childs; + if ($ename!="") $res = "<$ename $attrs>$res"; + return $res; + } + /** * load api $templatename for $type and replace $data array */ @@ -692,13 +716,17 @@ case "rss": case "xml": $data = array_xmlify($data); - $tpl = get_markup_template("api_".$templatename."_".$type.".tpl"); - if(! $tpl) { - header ("Content-Type: text/xml"); - echo ''."\n".'not implemented'; - killme(); + if ($templatename==="") { + $ret = api_array_to_xml($data); + } else { + $tpl = get_markup_template("api_".$templatename."_".$type.".tpl"); + if(! $tpl) { + header ("Content-Type: text/xml"); + echo ''."\n".'not implemented'; + killme(); + } + $ret = replace_macros($tpl, $data); } - $ret = replace_macros($tpl, $data); break; case "json": $ret = $data; @@ -3386,6 +3414,43 @@ api_register_func('api/friendica/activity/unattendno', 'api_friendica_activity', true, API_METHOD_POST); api_register_func('api/friendica/activity/unattendmaybe', 'api_friendica_activity', true, API_METHOD_POST); + /** + * returns notifications + * if called with note id set note seen and returns associated item (if possible) + */ + function api_friendica_notification(&$a, $type) { + if (api_user()===false) throw new ForbiddenException(); + + $nm = new NotificationsManager(); + + if ($a->argc==3) { + $notes = $nm->getAll(array(), "+seen -date", 50); + return api_apply_template("", $type, array('$notes' => $notes)); + } + if ($a->argc==4) { + $note = $nm->getByID(intval($a->argv[3])); + if (is_null($note)) throw new BadRequestException("Invalid argument"); + $nm->setSeen($note); + if ($note['otype']=='item') { + // would be really better with a ItemsManager and $im->getByID() :-P + $r = q("SELECT * FROM item WHERE id=%d AND uid=%d", + intval($note['iid']), + intval(local_user()) + ); + if ($r===false) throw new NotFoundException(); + $user_info = api_get_user($a); + $ret = api_format_items($r,$user_info); + $data = array('$statuses' => $ret); + return api_apply_template("timeline", $type, $data); + } else { + return api_apply_template('test', $type, array('ok' => $ok)); + } + + } + throw new BadRequestException("Invalid argument count"); + } + api_register_func('api/friendica/notification', 'api_friendica_notification', true, API_METHOD_GET); + /* To.Do: [pagename] => api/1.1/statuses/lookup.json diff --git a/mod/notify.php b/mod/notify.php index 7acac1084a..7c367708bb 100644 --- a/mod/notify.php +++ b/mod/notify.php @@ -1,43 +1,34 @@ argc > 2 && $a->argv[1] === 'view' && intval($a->argv[2])) { - $r = q("select * from notify where id = %d and uid = %d limit 1", - intval($a->argv[2]), - intval(local_user()) - ); - if(count($r)) { - q("update notify set seen = 1 where ( link = '%s' or ( parent != 0 and parent = %d and otype = '%s' )) and uid = %d", - dbesc($r[0]['link']), - intval($r[0]['parent']), - dbesc($r[0]['otype']), - intval(local_user()) - ); - + $note = $nm->getByID($a->argv[2]); + if ($note) { + $nm->setSeen($note); + // The friendica client has problems with the GUID. this is some workaround if ($a->is_friendica_app()) { require_once("include/items.php"); - $urldata = parse_url($r[0]['link']); + $urldata = parse_url($note['link']); $guid = basename($urldata["path"]); $itemdata = get_item_id($guid, local_user()); if ($itemdata["id"] != 0) - $r[0]['link'] = $a->get_baseurl().'/display/'.$itemdata["nick"].'/'.$itemdata["id"]; + $note['link'] = $a->get_baseurl().'/display/'.$itemdata["nick"].'/'.$itemdata["id"]; } - goaway($r[0]['link']); + goaway($note['link']); } goaway($a->get_baseurl(true)); } if($a->argc > 2 && $a->argv[1] === 'mark' && $a->argv[2] === 'all' ) { - $r = q("update notify set seen = 1 where uid = %d", - intval(local_user()) - ); + $r = $nm->setAllSeen(); $j = json_encode(array('result' => ($r) ? 'success' : 'fail')); echo $j; killme(); @@ -47,38 +38,37 @@ function notify_init(&$a) { if(! function_exists('notify_content')) { function notify_content(&$a) { - if(! local_user()) - return login(); + if(! local_user()) return login(); - $notif_tpl = get_markup_template('notifications.tpl'); + $nm = new NotificationsManager(); + + $notif_tpl = get_markup_template('notifications.tpl'); - $not_tpl = get_markup_template('notify.tpl'); - require_once('include/bbcode.php'); + $not_tpl = get_markup_template('notify.tpl'); + require_once('include/bbcode.php'); - $r = q("SELECT * from notify where uid = %d and seen = 0 order by date desc", - intval(local_user()) - ); - - if (count($r) > 0) { - foreach ($r as $it) { - $notif_content .= replace_macros($not_tpl,array( - '$item_link' => $a->get_baseurl(true).'/notify/view/'. $it['id'], - '$item_image' => $it['photo'], - '$item_text' => strip_tags(bbcode($it['msg'])), - '$item_when' => relative_date($it['date']) - )); - } - } else { - $notif_content .= t('No more system notifications.'); + $r = $nm->getAll(array('seen'=>0)); + if ($r!==false && count($r) > 0) { + foreach ($r as $it) { + $notif_content .= replace_macros($not_tpl,array( + '$item_link' => $a->get_baseurl(true).'/notify/view/'. $it['id'], + '$item_image' => $it['photo'], + '$item_text' => strip_tags(bbcode($it['msg'])), + '$item_when' => relative_date($it['date']) + )); } + } else { + $notif_content .= t('No more system notifications.'); + } - $o .= replace_macros($notif_tpl, array( - '$notif_header' => t('System Notifications'), - '$tabs' => '', // $tabs, - '$notif_content' => $notif_content, - )); + $o .= replace_macros($notif_tpl, array( + '$notif_header' => t('System Notifications'), + '$tabs' => false, // $tabs, + '$notif_content' => $notif_content, + )); return $o; } } + diff --git a/mod/ping.php b/mod/ping.php index 0d1659a763..adff0912f4 100644 --- a/mod/ping.php +++ b/mod/ping.php @@ -206,8 +206,8 @@ function ping_init(&$a) { $local_time = datetime_convert('UTC',date_default_timezone_get(),$n['date']); call_hooks('ping_xmlize', $n); - $notsxml = '%s'."\n"; - return sprintf ( $notsxml, + $notsxml = '%s'."\n"; + return sprintf ( $notsxml, intval($n['id']), xmlify($n['href']), xmlify($n['name']), xmlify($n['url']), xmlify($n['photo']), xmlify(relative_date($n['date'])), xmlify($n['seen']), xmlify(strtotime($local_time)), xmlify($n['message'])