Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

550 satır
15KB

  1. <?php
  2. require_once('include/datetime.php');
  3. require_once('include/bbcode.php');
  4. require_once('include/ForumManager.php');
  5. require_once('include/group.php');
  6. require_once('mod/proxy.php');
  7. require_once('include/xml.php');
  8. require_once('include/cache.php');
  9. /**
  10. * @brief Outputs the counts and the lists of various notifications
  11. *
  12. * The output format can be controlled via the GET parameter 'format'. It can be
  13. * - xml (deprecated legacy default)
  14. * - json (outputs JSONP with the 'callback' GET parameter)
  15. *
  16. * Expected JSON structure:
  17. * {
  18. * "result": {
  19. * "intro": 0,
  20. * "mail": 0,
  21. * "net": 0,
  22. * "home": 0,
  23. * "register": 0,
  24. * "all-events": 0,
  25. * "all-events-today": 0,
  26. * "events": 0,
  27. * "events-today": 0,
  28. * "birthdays": 0,
  29. * "birthdays-today": 0,
  30. * "groups": [ ],
  31. * "forums": [ ],
  32. * "notify": 0,
  33. * "notifications": [ ],
  34. * "sysmsgs": {
  35. * "notice": [ ],
  36. * "info": [ ]
  37. * }
  38. * }
  39. * }
  40. *
  41. * @param App $a The Friendica App instance
  42. */
  43. function ping_init(App $a)
  44. {
  45. $format = 'xml';
  46. if (isset($_GET['format']) && $_GET['format'] == 'json') {
  47. $format = 'json';
  48. }
  49. $tags = array();
  50. $comments = array();
  51. $likes = array();
  52. $dislikes = array();
  53. $friends = array();
  54. $posts = array();
  55. $regs = array();
  56. $mails = array();
  57. $notifications = array();
  58. $intro_count = 0;
  59. $mail_count = 0;
  60. $home_count = 0;
  61. $network_count = 0;
  62. $register_count = 0;
  63. $sysnotify_count = 0;
  64. $groups_unseen = array();
  65. $forums_unseen = array();
  66. $all_events = 0;
  67. $all_events_today = 0;
  68. $events = 0;
  69. $events_today = 0;
  70. $birthdays = 0;
  71. $birthdays_today = 0;
  72. $data = array();
  73. $data['intro'] = $intro_count;
  74. $data['mail'] = $mail_count;
  75. $data['net'] = $network_count;
  76. $data['home'] = $home_count;
  77. $data['register'] = $register_count;
  78. $data['all-events'] = $all_events;
  79. $data['all-events-today'] = $all_events_today;
  80. $data['events'] = $events;
  81. $data['events-today'] = $events_today;
  82. $data['birthdays'] = $birthdays;
  83. $data['birthdays-today'] = $birthdays_today;
  84. if (local_user()){
  85. // Different login session than the page that is calling us.
  86. if (intval($_GET['uid']) && intval($_GET['uid']) != local_user()) {
  87. $data = array('result' => array('invalid' => 1));
  88. if ($format == 'json') {
  89. if (isset($_GET['callback'])) {
  90. // JSONP support
  91. header("Content-type: application/javascript");
  92. echo $_GET['callback'] . '(' . json_encode($data) . ')';
  93. } else {
  94. header("Content-type: application/json");
  95. echo json_encode($data);
  96. }
  97. } else {
  98. header("Content-type: text/xml");
  99. echo xml::from_array($data, $xml);
  100. }
  101. killme();
  102. }
  103. $notifs = ping_get_notifications(local_user());
  104. $items_unseen = qu("SELECT `item`.`id`, `item`.`parent`, `item`.`verb`, `item`.`wall`, `item`.`author-name`,
  105. `item`.`contact-id`, `item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object`,
  106. `pitem`.`author-name` AS `pname`, `pitem`.`author-link` AS `plink`
  107. FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id` = `item`.`parent`
  108. WHERE `item`.`unseen` = 1 AND `item`.`visible` = 1 AND
  109. `item`.`deleted` = 0 AND `item`.`uid` = %d AND `pitem`.`parent` != 0
  110. AND `item`.`contact-id` != %d
  111. ORDER BY `item`.`created` DESC",
  112. intval(local_user()), intval(local_user())
  113. );
  114. if (dbm::is_result($items_unseen)) {
  115. $arr = array('items' => $items_unseen);
  116. call_hooks('network_ping', $arr);
  117. foreach ($items_unseen as $item) {
  118. if ($item['wall']) {
  119. $home_count++;
  120. } else {
  121. $network_count++;
  122. }
  123. }
  124. }
  125. if ($network_count) {
  126. if (intval(feature_enabled(local_user(), 'groups'))) {
  127. // Find out how unseen network posts are spread across groups
  128. $group_counts = groups_count_unseen();
  129. if (dbm::is_result($group_counts)) {
  130. foreach ($group_counts as $group_count) {
  131. if ($group_count['count'] > 0) {
  132. $groups_unseen[] = $group_count;
  133. }
  134. }
  135. }
  136. }
  137. if (intval(feature_enabled(local_user(), 'forumlist_widget'))) {
  138. $forum_counts = ForumManager::count_unseen_items();
  139. if (dbm::is_result($forums_counts)) {
  140. foreach ($forums_counts as $forum_count) {
  141. if ($forum_count['count'] > 0) {
  142. $forums_unseen[] = $forum_count;
  143. }
  144. }
  145. }
  146. }
  147. }
  148. $intros1 = qu("SELECT `intro`.`id`, `intro`.`datetime`,
  149. `fcontact`.`name`, `fcontact`.`url`, `fcontact`.`photo`
  150. FROM `intro` LEFT JOIN `fcontact` ON `intro`.`fid` = `fcontact`.`id`
  151. WHERE `intro`.`uid` = %d AND `intro`.`blocked` = 0 AND `intro`.`ignore` = 0 AND `intro`.`fid` != 0",
  152. intval(local_user())
  153. );
  154. $intros2 = qu("SELECT `intro`.`id`, `intro`.`datetime`,
  155. `contact`.`name`, `contact`.`url`, `contact`.`photo`
  156. FROM `intro` LEFT JOIN `contact` ON `intro`.`contact-id` = `contact`.`id`
  157. WHERE `intro`.`uid` = %d AND `intro`.`blocked` = 0 AND `intro`.`ignore` = 0 AND `intro`.`contact-id` != 0",
  158. intval(local_user())
  159. );
  160. $intro_count = count($intros1) + count($intros2);
  161. $intros = $intros1 + $intros2;
  162. $myurl = App::get_baseurl() . '/profile/' . $a->user['nickname'] ;
  163. $mails = qu("SELECT `id`, `from-name`, `from-url`, `from-photo`, `created` FROM `mail`
  164. WHERE `uid` = %d AND `seen` = 0 AND `from-url` != '%s' ",
  165. intval(local_user()),
  166. dbesc($myurl)
  167. );
  168. $mail_count = count($mails);
  169. if ($a->config['register_policy'] == REGISTER_APPROVE && is_site_admin()){
  170. $regs = qu("SELECT `contact`.`name`, `contact`.`url`, `contact`.`micro`, `register`.`created`, COUNT(*) AS `total`
  171. FROM `contact` RIGHT JOIN `register` ON `register`.`uid` = `contact`.`uid`
  172. WHERE `contact`.`self` = 1");
  173. if (dbm::is_result($regs)) {
  174. $register_count = $regs[0]['total'];
  175. }
  176. }
  177. $cachekey = "ping_init:".local_user();
  178. $ev = Cache::get($cachekey);
  179. if (is_null($ev)) {
  180. $ev = qu("SELECT type, start, adjust FROM `event`
  181. WHERE `event`.`uid` = %d AND `start` < '%s' AND `finish` > '%s' and `ignore` = 0
  182. ORDER BY `start` ASC ",
  183. intval(local_user()),
  184. dbesc(datetime_convert('UTC', 'UTC', 'now + 7 days')),
  185. dbesc(datetime_convert('UTC', 'UTC', 'now'))
  186. );
  187. if (dbm::is_result($ev)) {
  188. Cache::set($cachekey, $ev, CACHE_HOUR);
  189. }
  190. }
  191. if (dbm::is_result($ev)) {
  192. $all_events = count($ev);
  193. if ($all_events) {
  194. $str_now = datetime_convert('UTC', $a->timezone, 'now', 'Y-m-d');
  195. foreach($ev as $x) {
  196. $bd = false;
  197. if ($x['type'] === 'birthday') {
  198. $birthdays ++;
  199. $bd = true;
  200. }
  201. else {
  202. $events ++;
  203. }
  204. if (datetime_convert('UTC', ((intval($x['adjust'])) ? $a->timezone : 'UTC'), $x['start'], 'Y-m-d') === $str_now) {
  205. $all_events_today ++;
  206. if ($bd)
  207. $birthdays_today ++;
  208. else
  209. $events_today ++;
  210. }
  211. }
  212. }
  213. }
  214. $data['intro'] = $intro_count;
  215. $data['mail'] = $mail_count;
  216. $data['net'] = $network_count;
  217. $data['home'] = $home_count;
  218. $data['register'] = $register_count;
  219. $data['all-events'] = $all_events;
  220. $data['all-events-today'] = $all_events_today;
  221. $data['events'] = $events;
  222. $data['events-today'] = $events_today;
  223. $data['birthdays'] = $birthdays;
  224. $data['birthdays-today'] = $birthdays_today;
  225. if (dbm::is_result($notifs)) {
  226. foreach ($notifs as $notif) {
  227. if ($notif['seen'] == 0) {
  228. $sysnotify_count ++;
  229. }
  230. }
  231. }
  232. // merge all notification types in one array
  233. if (dbm::is_result($intros)) {
  234. foreach ($intros as $intro) {
  235. $notif = array(
  236. 'href' => App::get_baseurl() . '/notifications/intros/' . $intro['id'],
  237. 'name' => $intro['name'],
  238. 'url' => $intro['url'],
  239. 'photo' => $intro['photo'],
  240. 'date' => $intro['datetime'],
  241. 'seen' => false,
  242. 'message' => t('{0} wants to be your friend'),
  243. );
  244. $notifs[] = $notif;
  245. }
  246. }
  247. if (dbm::is_result($mails)) {
  248. foreach ($mails as $mail) {
  249. $notif = array(
  250. 'href' => App::get_baseurl() . '/message/' . $mail['id'],
  251. 'name' => $mail['from-name'],
  252. 'url' => $mail['from-url'],
  253. 'photo' => $mail['from-photo'],
  254. 'date' => $mail['created'],
  255. 'seen' => false,
  256. 'message' => t('{0} sent you a message'),
  257. );
  258. $notifs[] = $notif;
  259. }
  260. }
  261. if (dbm::is_result($regs)) {
  262. foreach ($regs as $reg) {
  263. $notif = array(
  264. 'href' => App::get_baseurl() . '/admin/users/',
  265. 'name' => $reg['name'],
  266. 'url' => $reg['url'],
  267. 'photo' => $reg['micro'],
  268. 'date' => $reg['created'],
  269. 'seen' => false,
  270. 'message' => t('{0} requested registration'),
  271. );
  272. $notifs[] = $notif;
  273. }
  274. }
  275. // sort notifications by $[]['date']
  276. $sort_function = function($a, $b) {
  277. $adate = strtotime($a['date']);
  278. $bdate = strtotime($b['date']);
  279. // Unseen messages are kept at the top
  280. // The value 31536000 means one year. This should be enough :-)
  281. if (!$a['seen']) {
  282. $adate += 31536000;
  283. }
  284. if (!$b['seen']) {
  285. $bdate += 31536000;
  286. }
  287. if ($adate == $bdate) {
  288. return 0;
  289. }
  290. return ($adate < $bdate) ? 1 : -1;
  291. };
  292. usort($notifs, $sort_function);
  293. if (dbm::is_result($notifs)) {
  294. // Are the nofications called from the regular process or via the friendica app?
  295. $regularnotifications = (intval($_GET['uid']) AND intval($_GET['_']));
  296. foreach ($notifs as $notif) {
  297. if ($a->is_friendica_app() OR !$regularnotifications) {
  298. $notif['message'] = str_replace("{0}", $notif['name'], $notif['message']);
  299. }
  300. $contact = get_contact_details_by_url($notif['url']);
  301. if (isset($contact['micro'])) {
  302. $notif['photo'] = proxy_url($contact['micro'], false, PROXY_SIZE_MICRO);
  303. } else {
  304. $notif['photo'] = proxy_url($notif['photo'], false, PROXY_SIZE_MICRO);
  305. }
  306. $local_time = datetime_convert('UTC', date_default_timezone_get(), $notif['date']);
  307. $notifications[] = array(
  308. 'id' => $notif['id'],
  309. 'href' => $notif['href'],
  310. 'name' => $notif['name'],
  311. 'url' => $notif['url'],
  312. 'photo' => $notif['photo'],
  313. 'date' => relative_date($notif['date']),
  314. 'message' => $notif['message'],
  315. 'seen' => $notif['seen'],
  316. 'timestamp' => strtotime($local_time)
  317. );
  318. }
  319. }
  320. }
  321. $sysmsgs = array();
  322. $sysmsgs_info = array();
  323. if (x($_SESSION, 'sysmsg')) {
  324. $sysmsgs = $_SESSION['sysmsg'];
  325. unset($_SESSION['sysmsg']);
  326. }
  327. if (x($_SESSION, 'sysmsg_info')) {
  328. $sysmsgs_info = $_SESSION['sysmsg_info'];
  329. unset($_SESSION['sysmsg_info']);
  330. }
  331. if ($format == 'json') {
  332. $data['groups'] = $groups_unseen;
  333. $data['forums'] = $forums_unseen;
  334. $data['notify'] = $sysnotify_count + $intro_count + $mail_count + $register_count;
  335. $data['notifications'] = $notifications;
  336. $data['sysmsgs'] = array(
  337. 'notice' => $sysmsgs,
  338. 'info' => $sysmsgs_info
  339. );
  340. $json_payload = json_encode(array("result" => $data));
  341. if (isset($_GET['callback'])) {
  342. // JSONP support
  343. header("Content-type: application/javascript");
  344. echo $_GET['callback'] . '(' . $json_payload . ')';
  345. } else {
  346. header("Content-type: application/json");
  347. echo $json_payload;
  348. }
  349. } else {
  350. // Legacy slower XML format output
  351. $data = ping_format_xml_data($data, $sysnotify_count, $notifications, $sysmsgs, $sysmsgs_info, $groups_unseen, $forums_unseen);
  352. header("Content-type: text/xml");
  353. echo xml::from_array(array("result" => $data), $xml);
  354. }
  355. killme();
  356. }
  357. /**
  358. * @brief Retrieves the notifications array for the given user ID
  359. *
  360. * @param int $uid User id
  361. * @return array Associative array of notifications
  362. */
  363. function ping_get_notifications($uid)
  364. {
  365. $result = array();
  366. $offset = 0;
  367. $seen = false;
  368. $seensql = "NOT";
  369. $order = "DESC";
  370. $quit = false;
  371. $a = get_app();
  372. do {
  373. $r = qu("SELECT `notify`.*, `item`.`visible`, `item`.`spam`, `item`.`deleted`
  374. FROM `notify` LEFT JOIN `item` ON `item`.`id` = `notify`.`iid`
  375. WHERE `notify`.`uid` = %d AND `notify`.`msg` != ''
  376. AND NOT (`notify`.`type` IN (%d, %d))
  377. AND $seensql `notify`.`seen` ORDER BY `notify`.`date` $order LIMIT %d, 50",
  378. intval($uid),
  379. intval(NOTIFY_INTRO),
  380. intval(NOTIFY_MAIL),
  381. intval($offset)
  382. );
  383. if (!$r AND !$seen) {
  384. $seen = true;
  385. $seensql = "";
  386. $order = "DESC";
  387. $offset = 0;
  388. } elseif (!$r) {
  389. $quit = true;
  390. } else {
  391. $offset += 50;
  392. }
  393. foreach ($r AS $notification) {
  394. if (is_null($notification["visible"])) {
  395. $notification["visible"] = true;
  396. }
  397. if (is_null($notification["spam"])) {
  398. $notification["spam"] = 0;
  399. }
  400. if (is_null($notification["deleted"])) {
  401. $notification["deleted"] = 0;
  402. }
  403. if ($notification["msg_cache"]) {
  404. $notification["name"] = $notification["name_cache"];
  405. $notification["message"] = $notification["msg_cache"];
  406. } else {
  407. $notification["name"] = strip_tags(bbcode($notification["name"]));
  408. $notification["message"] = format_notification_message($notification["name"], strip_tags(bbcode($notification["msg"])));
  409. q("UPDATE `notify` SET `name_cache` = '%s', `msg_cache` = '%s' WHERE `id` = %d",
  410. dbesc($notification["name"]),
  411. dbesc($notification["message"]),
  412. intval($notification["id"])
  413. );
  414. }
  415. $notification["href"] = App::get_baseurl() . "/notify/view/" . $notification["id"];
  416. if ($notification["visible"] AND !$notification["spam"] AND
  417. !$notification["deleted"] AND !is_array($result[$notification["parent"]])) {
  418. $result[$notification["parent"]] = $notification;
  419. }
  420. }
  421. } while ((count($result) < 50) AND !$quit);
  422. return($result);
  423. }
  424. /**
  425. * @brief Backward-compatible XML formatting for ping.php output
  426. * @deprecated
  427. *
  428. * @param array $data The initial ping data array
  429. * @param int $sysnotify_count Number of unseen system notifications
  430. * @param array $notifs Complete list of notification
  431. * @param array $sysmsgs List of system notice messages
  432. * @param array $sysmsgs_info List of system info messages
  433. * @param int $groups_unseen Number of unseen group items
  434. * @param int $forums_unseen Number of unseen forum items
  435. * @return array XML-transform ready data array
  436. */
  437. function ping_format_xml_data($data, $sysnotify, $notifs, $sysmsgs, $sysmsgs_info, $groups_unseen, $forums_unseen)
  438. {
  439. $notifications = array();
  440. foreach($notifs as $key => $notif) {
  441. $notifications[$key . ':note'] = $notif['message'];
  442. $notifications[$key . ':@attributes'] = array(
  443. 'id' => $notif['id'],
  444. 'href' => $notif['href'],
  445. 'name' => $notif['name'],
  446. 'url' => $notif['url'],
  447. 'photo' => $notif['photo'],
  448. 'date' => $notif['date'],
  449. 'seen' => $notif['seen'],
  450. 'timestamp' => $notif['timestamp']
  451. );
  452. }
  453. $sysmsg = array();
  454. foreach ($sysmsgs as $key => $m){
  455. $sysmsg[$key . ':notice'] = $m;
  456. }
  457. foreach ($sysmsgs_info as $key => $m){
  458. $sysmsg[$key . ':info'] = $m;
  459. }
  460. $data['notif'] = $notifications;
  461. $data['@attributes'] = array('count' => $sysnotify_count + $data['intro'] + $data['mail'] + $data['register']);
  462. $data['sysmsgs'] = $sysmsg;
  463. if ($data['register'] == 0) {
  464. unset($data['register']);
  465. }
  466. $groups = array();
  467. if (count($groups_unseen)) {
  468. foreach ($groups_unseen as $key => $item) {
  469. $groups[$key . ':group'] = $item['count'];
  470. $groups[$key . ':@attributes'] = array('id' => $item['id']);
  471. }
  472. $data['groups'] = $groups;
  473. }
  474. $forums = array();
  475. if (count($forums_unseen)) {
  476. foreach ($forums_unseen as $key => $item) {
  477. $forums[$count . ':forum'] = $item['count'];
  478. $forums[$count . ':@attributes'] = array('id' => $item['id']);
  479. }
  480. $data['forums'] = $forums;
  481. }
  482. return $data;
  483. }