Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

970 lines
28KB

  1. <?php
  2. use Friendica\App;
  3. use Friendica\Core\System;
  4. use Friendica\Core\Config;
  5. use Friendica\Core\PConfig;
  6. require_once 'include/conversation.php';
  7. require_once 'include/group.php';
  8. require_once 'include/contact_widgets.php';
  9. require_once 'include/items.php';
  10. require_once 'include/ForumManager.php';
  11. require_once 'include/acl_selectors.php';
  12. function network_init(App $a) {
  13. if (!local_user()) {
  14. notice(t('Permission denied.') . EOL);
  15. return;
  16. }
  17. $search = (x($_GET, 'search') ? escape_tags($_GET['search']) : '');
  18. if (($search != '') && !empty($_GET['submit'])) {
  19. goaway('search?search='.urlencode($search));
  20. }
  21. if (x($_GET, 'save')) {
  22. $exists = dba::exists('search', array('uid' => local_user(), 'term' => $search));
  23. if (!$exists) {
  24. dba::insert('search', array('uid' => local_user(), 'term' => $search));
  25. }
  26. }
  27. if (x($_GET, 'remove')) {
  28. dba::delete('search', array('uid' => local_user(), 'term' => $search));
  29. }
  30. $is_a_date_query = false;
  31. if (x($_GET, 'cid') && intval($_GET['cid']) != 0) {
  32. $cid = $_GET['cid'];
  33. $_GET['nets'] = 'all';
  34. }
  35. if ($a->argc > 1) {
  36. for ($x = 1; $x < $a->argc; $x ++) {
  37. if (is_a_date_arg($a->argv[$x])) {
  38. $is_a_date_query = true;
  39. break;
  40. }
  41. }
  42. }
  43. // convert query string to array. remove friendica args
  44. $query_array = array();
  45. $query_string = str_replace($a->cmd."?", "", $a->query_string);
  46. parse_str($query_string, $query_array);
  47. array_shift($query_array);
  48. // fetch last used network view and redirect if needed
  49. if (!$is_a_date_query) {
  50. $sel_tabs = network_query_get_sel_tab($a);
  51. $sel_nets = network_query_get_sel_net();
  52. $sel_groups = network_query_get_sel_group($a);
  53. $last_sel_tabs = PConfig::get(local_user(), 'network.view','tab.selected');
  54. $last_sel_nets = PConfig::get(local_user(), 'network.view', 'net.selected');
  55. $last_sel_groups = PConfig::get(local_user(), 'network.view', 'group.selected');
  56. $remember_tab = ($sel_tabs[0] === 'active' && is_array($last_sel_tabs) && $last_sel_tabs[0] !== 'active');
  57. $remember_net = ($sel_nets === false && $last_sel_nets && $last_sel_nets !== 'all');
  58. $remember_group = ($sel_groups === false && $last_sel_groups && $last_sel_groups != 0);
  59. $net_baseurl = '/network';
  60. $net_args = array();
  61. if ($remember_group) {
  62. $net_baseurl .= '/' . $last_sel_groups; // Note that the group number must come before the "/new" tab selection
  63. } elseif ($sel_groups !== false) {
  64. $net_baseurl .= '/' . $sel_groups;
  65. }
  66. if ($remember_tab) {
  67. // redirect if current selected tab is '/network' and
  68. // last selected tab is _not_ '/network?f=&order=comment'.
  69. // and this isn't a date query
  70. $tab_baseurls = array(
  71. '', //all
  72. '', //postord
  73. '', //conv
  74. '/new', //new
  75. '', //starred
  76. '', //bookmarked
  77. '', //spam
  78. );
  79. $tab_args = array(
  80. 'f=&order=comment', //all
  81. 'f=&order=post', //postord
  82. 'f=&conv=1', //conv
  83. '', //new
  84. 'f=&star=1', //starred
  85. 'f=&bmark=1', //bookmarked
  86. 'f=&spam=1', //spam
  87. );
  88. $k = array_search('active', $last_sel_tabs);
  89. if ($k != 3) {
  90. $net_baseurl .= $tab_baseurls[$k];
  91. // parse out tab queries
  92. $dest_qa = array();
  93. $dest_qs = $tab_args[$k];
  94. parse_str($dest_qs, $dest_qa);
  95. $net_args = array_merge($net_args, $dest_qa);
  96. } else {
  97. $remember_tab = false;
  98. }
  99. } elseif ($sel_tabs[4] === 'active') {
  100. // The '/new' tab is selected
  101. $remember_group = false;
  102. }
  103. if ($remember_net) {
  104. $net_args['nets'] = $last_sel_nets;
  105. } elseif ($sel_nets!==false) {
  106. $net_args['nets'] = $sel_nets;
  107. }
  108. if ($remember_tab || $remember_net || $remember_group) {
  109. $net_args = array_merge($query_array, $net_args);
  110. $net_queries = build_querystring($net_args);
  111. $redir_url = ($net_queries ? $net_baseurl."?".$net_queries : $net_baseurl);
  112. goaway(System::baseUrl() . $redir_url);
  113. }
  114. }
  115. // If nets is set to all, unset it
  116. if (x($_GET, 'nets') && $_GET['nets'] === 'all') {
  117. unset($_GET['nets']);
  118. }
  119. $group_id = (($a->argc > 1 && is_numeric($a->argv[1])) ? intval($a->argv[1]) : 0);
  120. PConfig::set(local_user(), 'network.view', 'group.selected', $group_id);
  121. if (!x($a->page, 'aside')) {
  122. $a->page['aside'] = '';
  123. }
  124. $a->page['aside'] .= (feature_enabled(local_user(),'groups') ? group_side('network/0','network','standard',$group_id) : '');
  125. $a->page['aside'] .= (feature_enabled(local_user(),'forumlist_widget') ? ForumManager::widget(local_user(),$cid) : '');
  126. $a->page['aside'] .= posted_date_widget('network',local_user(),false);
  127. $a->page['aside'] .= networks_widget('network',(x($_GET, 'nets') ? $_GET['nets'] : ''));
  128. $a->page['aside'] .= saved_searches($search);
  129. $a->page['aside'] .= fileas_widget('network',(x($_GET, 'file') ? $_GET['file'] : ''));
  130. }
  131. function saved_searches($search) {
  132. if (!feature_enabled(local_user(),'savedsearch')) {
  133. return '';
  134. }
  135. $a = get_app();
  136. $srchurl = '/network?f='
  137. . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '')
  138. . ((x($_GET,'star')) ? '&star=' . $_GET['star'] : '')
  139. . ((x($_GET,'bmark')) ? '&bmark=' . $_GET['bmark'] : '')
  140. . ((x($_GET,'conv')) ? '&conv=' . $_GET['conv'] : '')
  141. . ((x($_GET,'nets')) ? '&nets=' . $_GET['nets'] : '')
  142. . ((x($_GET,'cmin')) ? '&cmin=' . $_GET['cmin'] : '')
  143. . ((x($_GET,'cmax')) ? '&cmax=' . $_GET['cmax'] : '')
  144. . ((x($_GET,'file')) ? '&file=' . $_GET['file'] : '');
  145. ;
  146. $o = '';
  147. $terms = dba::select('search', array('id', 'term'), array('uid' => local_user()));
  148. $saved = array();
  149. while ($rr = dba::fetch($terms)) {
  150. $saved[] = array(
  151. 'id' => $rr['id'],
  152. 'term' => $rr['term'],
  153. 'encodedterm' => urlencode($rr['term']),
  154. 'delete' => t('Remove term'),
  155. 'selected' => ($search==$rr['term']),
  156. );
  157. }
  158. $tpl = get_markup_template("saved_searches_aside.tpl");
  159. $o = replace_macros($tpl, array(
  160. '$title' => t('Saved Searches'),
  161. '$add' => t('add'),
  162. '$searchbox' => search($search,'netsearch-box',$srchurl,true),
  163. '$saved' => $saved,
  164. ));
  165. return $o;
  166. }
  167. /**
  168. * Return selected tab from query
  169. *
  170. * urls -> returns
  171. * '/network' => $no_active = 'active'
  172. * '/network?f=&order=comment' => $comment_active = 'active'
  173. * '/network?f=&order=post' => $postord_active = 'active'
  174. * '/network?f=&conv=1', => $conv_active = 'active'
  175. * '/network/new', => $new_active = 'active'
  176. * '/network?f=&star=1', => $starred_active = 'active'
  177. * '/network?f=&bmark=1', => $bookmarked_active = 'active'
  178. * '/network?f=&spam=1', => $spam_active = 'active'
  179. *
  180. * @return Array ($no_active, $comment_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active, $spam_active);
  181. */
  182. function network_query_get_sel_tab(App $a) {
  183. $no_active='';
  184. $starred_active = '';
  185. $new_active = '';
  186. $bookmarked_active = '';
  187. $all_active = '';
  188. $conv_active = '';
  189. $spam_active = '';
  190. $postord_active = '';
  191. if (($a->argc > 1 && $a->argv[1] === 'new')
  192. || ($a->argc > 2 && $a->argv[2] === 'new')) {
  193. $new_active = 'active';
  194. }
  195. if (x($_GET,'star')) {
  196. $starred_active = 'active';
  197. }
  198. if (x($_GET,'bmark')) {
  199. $bookmarked_active = 'active';
  200. }
  201. if (x($_GET,'conv')) {
  202. $conv_active = 'active';
  203. }
  204. if (x($_GET,'spam')) {
  205. $spam_active = 'active';
  206. }
  207. if (($new_active == '')
  208. && ($starred_active == '')
  209. && ($bookmarked_active == '')
  210. && ($conv_active == '')
  211. && ($spam_active == '')) {
  212. $no_active = 'active';
  213. }
  214. if ($no_active=='active' && x($_GET,'order')) {
  215. switch($_GET['order']){
  216. case 'post': $postord_active = 'active'; $no_active=''; break;
  217. case 'comment' : $all_active = 'active'; $no_active=''; break;
  218. }
  219. }
  220. return array($no_active, $all_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active, $spam_active);
  221. }
  222. /**
  223. * @brief Return selected network from query
  224. * @return string Name of the selected network
  225. */
  226. function network_query_get_sel_net() {
  227. $network = false;
  228. if (x($_GET,'nets')) {
  229. $network = $_GET['nets'];
  230. }
  231. return $network;
  232. }
  233. function network_query_get_sel_group(App $a) {
  234. $group = false;
  235. if ($a->argc >= 2 && is_numeric($a->argv[1])) {
  236. $group = $a->argv[1];
  237. }
  238. return $group;
  239. }
  240. /**
  241. * @brief Sets the pager data and returns SQL
  242. *
  243. * @param App $a The global App
  244. * @param integer $update Used for the automatic reloading
  245. * @return string SQL with the appropriate LIMIT clause
  246. */
  247. function networkPager($a, $update) {
  248. if ($update) {
  249. // only setup pagination on initial page view
  250. return ' LIMIT 100';
  251. }
  252. // check if we serve a mobile device and get the user settings
  253. // accordingly
  254. if ($a->is_mobile) {
  255. $itemspage_network = PConfig::get(local_user(),'system','itemspage_mobile_network');
  256. $itemspage_network = ((intval($itemspage_network)) ? $itemspage_network : 20);
  257. } else {
  258. $itemspage_network = PConfig::get(local_user(),'system','itemspage_network');
  259. $itemspage_network = ((intval($itemspage_network)) ? $itemspage_network : 40);
  260. }
  261. // now that we have the user settings, see if the theme forces
  262. // a maximum item number which is lower then the user choice
  263. if (($a->force_max_items > 0) && ($a->force_max_items < $itemspage_network)) {
  264. $itemspage_network = $a->force_max_items;
  265. }
  266. $a->set_pager_itemspage($itemspage_network);
  267. return sprintf(" LIMIT %d, %d ",intval($a->pager['start']), intval($a->pager['itemspage']));
  268. }
  269. /**
  270. * @brief Sets items as seen
  271. *
  272. * @param array $condition The array with the SQL condition
  273. */
  274. function networkSetSeen($condition) {
  275. if (empty($condition)) {
  276. return;
  277. }
  278. $unseen = dba::exists('item', $condition);
  279. if ($unseen) {
  280. $r = dba::update('item', array('unseen' => false), $condition);
  281. }
  282. }
  283. /**
  284. * @brief Create the conversation HTML
  285. *
  286. * @param App $a The global App
  287. * @param array $items Items of the conversation
  288. * @param string $mode Display mode for the conversation
  289. * @param integer $update Used for the automatic reloading
  290. * @return string HTML of the conversation
  291. */
  292. function networkConversation($a, $items, $mode, $update) {
  293. // Set this so that the conversation function can find out contact info for our wall-wall items
  294. $a->page_contact = $a->contact;
  295. $o .= conversation($a, $items, $mode, $update);
  296. if (!$update) {
  297. if (PConfig::get(local_user(), 'system', 'infinite_scroll')) {
  298. $o .= scroll_loader();
  299. } else {
  300. $o .= alt_pager($a, count($items));
  301. }
  302. }
  303. return $o;
  304. }
  305. function network_content(App $a, $update = 0) {
  306. if (!local_user()) {
  307. $_SESSION['return_url'] = $a->query_string;
  308. return login(false);
  309. }
  310. /// @TODO Is this really necessary? $a is already available to hooks
  311. $arr = array('query' => $a->query_string);
  312. call_hooks('network_content_init', $arr);
  313. $nouveau = false;
  314. if ($a->argc > 1) {
  315. for ($x = 1; $x < $a->argc; $x ++) {
  316. if ($a->argv[$x] === 'new') {
  317. $nouveau = true;
  318. }
  319. }
  320. }
  321. if (x($_GET,'file')) {
  322. $nouveau = true;
  323. }
  324. if ($nouveau) {
  325. $o = networkFlatView($a, $update);
  326. } else {
  327. $o = networkThreadedView($a, $update);
  328. }
  329. return $o;
  330. }
  331. /**
  332. * @brief Get the network content in flat view
  333. *
  334. * @param App $a The global App
  335. * @param integer $update Used for the automatic reloading
  336. * @return string HTML of the network content in flat view
  337. */
  338. function networkFlatView(App $a, $update = 0) {
  339. // Rawmode is used for fetching new content at the end of the page
  340. $rawmode = (isset($_GET["mode"]) AND ($_GET["mode"] == "raw"));
  341. if (isset($_GET["last_id"])) {
  342. $last_id = intval($_GET["last_id"]);
  343. } else {
  344. $last_id = 0;
  345. }
  346. $o = '';
  347. $file = ((x($_GET,'file')) ? $_GET['file'] : '');
  348. PConfig::set(local_user(), 'network.view', 'net.selected', 'all');
  349. if (!$update && !$rawmode) {
  350. $tabs = network_tabs($a);
  351. $o .= $tabs;
  352. nav_set_selected('network');
  353. $x = array(
  354. 'is_owner' => true,
  355. 'allow_location' => $a->user['allow_location'],
  356. 'default_location' => $a->user['default-location'],
  357. 'nickname' => $a->user['nickname'],
  358. 'lockstate'=> (((is_array($a->user) &&
  359. ((strlen($a->user['allow_cid'])) || (strlen($a->user['allow_gid'])) ||
  360. (strlen($a->user['deny_cid'])) || (strlen($a->user['deny_gid']))))) ? 'lock' : 'unlock'),
  361. 'default_perms' => get_acl_permissions($a->user),
  362. 'acl' => populate_acl($a->user, true),
  363. 'bang' => '',
  364. 'visitor' => 'block',
  365. 'profile_uid' => local_user(),
  366. 'acl_data' => construct_acl_data($a, $a->user), // For non-Javascript ACL selector
  367. 'content' => '',
  368. );
  369. $o .= status_editor($a,$x);
  370. if (!Config::get('theme','hide_eventlist')) {
  371. $o .= get_birthdays();
  372. $o .= get_events();
  373. }
  374. }
  375. if (strlen($file)) {
  376. $sql_post_table .= sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ",
  377. dbesc(protect_sprintf($file)), intval(TERM_OBJ_POST), intval(TERM_FILE), intval(local_user()));
  378. } else {
  379. $sql_post_table = " INNER JOIN `thread` ON `thread`.`iid` = `item`.`parent`";
  380. }
  381. $pager_sql = networkPager($a, $update);
  382. // show all items unthreaded in reverse created date order
  383. $items = q("SELECT %s FROM `item` $sql_post_table %s
  384. WHERE %s AND `item`.`uid` = %d
  385. ORDER BY `item`.`id` DESC $pager_sql ",
  386. item_fieldlists(), item_joins(), item_condition(),
  387. intval($_SESSION['uid'])
  388. );
  389. $condition = array('unseen' => true, 'uid' => local_user());
  390. networkSetSeen($condition);
  391. $mode = 'network-new';
  392. $o .= networkConversation($a, $items, $mode, $update);
  393. return $o;
  394. }
  395. /**
  396. * @brief Get the network content in threaded view
  397. *
  398. * @param App $a The global App
  399. * @param integer $update Used for the automatic reloading
  400. * @return string HTML of the network content in flat view
  401. */
  402. function networkThreadedView(App $a, $update = 0) {
  403. // Rawmode is used for fetching new content at the end of the page
  404. $rawmode = (isset($_GET["mode"]) AND ($_GET["mode"] == "raw"));
  405. if (isset($_GET["last_received"]) && isset($_GET["last_commented"]) && isset($_GET["last_created"]) && isset($_GET["last_id"])) {
  406. $last_received = dbm::date($_GET["last_received"]);
  407. $last_commented = dbm::date($_GET["last_commented"]);
  408. $last_created = dbm::date($_GET["last_created"]);
  409. $last_id = intval($_GET["last_id"]);
  410. } else {
  411. $last_received = '';
  412. $last_commented = '';
  413. $last_created = '';
  414. $last_id = 0;
  415. }
  416. $datequery = $datequery2 = '';
  417. $group = 0;
  418. if ($a->argc > 1) {
  419. for ($x = 1; $x < $a->argc; $x ++) {
  420. if (is_a_date_arg($a->argv[$x])) {
  421. if ($datequery) {
  422. $datequery2 = escape_tags($a->argv[$x]);
  423. } else {
  424. $datequery = escape_tags($a->argv[$x]);
  425. $_GET['order'] = 'post';
  426. }
  427. } elseif (intval($a->argv[$x])) {
  428. $group = intval($a->argv[$x]);
  429. $def_acl = array('allow_gid' => '<' . $group . '>');
  430. }
  431. }
  432. }
  433. $o = '';
  434. $cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0);
  435. $star = ((x($_GET,'star')) ? intval($_GET['star']) : 0);
  436. $bmark = ((x($_GET,'bmark')) ? intval($_GET['bmark']) : 0);
  437. $order = ((x($_GET,'order')) ? notags($_GET['order']) : 'comment');
  438. $conv = ((x($_GET,'conv')) ? intval($_GET['conv']) : 0);
  439. $nets = ((x($_GET,'nets')) ? $_GET['nets'] : '');
  440. if ($cid) {
  441. $def_acl = array('allow_cid' => '<' . intval($cid) . '>');
  442. }
  443. if ($nets) {
  444. $r = dba::select('contact', array('id'), array('uid' => local_user(), 'network' => $nets), array('self' => false));
  445. $str = '';
  446. while ($rr = dba::fetch($r)) {
  447. $str .= '<' . $rr['id'] . '>';
  448. }
  449. if (strlen($str)) {
  450. $def_acl = array('allow_cid' => $str);
  451. }
  452. }
  453. PConfig::set(local_user(), 'network.view', 'net.selected', ($nets ? $nets : 'all'));
  454. if (!$update && !$rawmode) {
  455. $tabs = network_tabs($a);
  456. $o .= $tabs;
  457. if ($group) {
  458. if (($t = group_public_members($group)) && !PConfig::get(local_user(),'system','nowarn_insecure')) {
  459. notice(sprintf(tt("Warning: This group contains %s member from a network that doesn't allow non public messages.",
  460. "Warning: This group contains %s members from a network that doesn't allow non public messages.",
  461. $t), $t).EOL);
  462. notice(t("Messages in this group won't be send to these receivers.").EOL);
  463. }
  464. }
  465. nav_set_selected('network');
  466. $content = "";
  467. if ($cid) {
  468. // If $cid belongs to a communitity forum or a privat goup,.add a mention to the status editor
  469. $condition = array("`id` = ? AND (`forum` OR `prv`)", $cid);
  470. $contact = dba::select('contact', array('addr', 'nick'), $condition, array('limit' => 1));
  471. if (dbm::is_result($contact)) {
  472. if ($contact["addr"] != '') {
  473. $content = "!".$contact["addr"];
  474. } else {
  475. $content = "!".$contact["nick"]."+".$cid;
  476. }
  477. }
  478. }
  479. $x = array(
  480. 'is_owner' => true,
  481. 'allow_location' => $a->user['allow_location'],
  482. 'default_location' => $a->user['default-location'],
  483. 'nickname' => $a->user['nickname'],
  484. 'lockstate'=> ((($group) || ($cid) || ($nets) || (is_array($a->user) &&
  485. ((strlen($a->user['allow_cid'])) || (strlen($a->user['allow_gid'])) ||
  486. (strlen($a->user['deny_cid'])) || (strlen($a->user['deny_gid']))))) ? 'lock' : 'unlock'),
  487. 'default_perms' => get_acl_permissions($a->user),
  488. 'acl' => populate_acl((($group || $cid || $nets) ? $def_acl : $a->user), true),
  489. 'bang' => (($group || $cid || $nets) ? '!' : ''),
  490. 'visitor' => 'block',
  491. 'profile_uid' => local_user(),
  492. 'acl_data' => construct_acl_data($a, $a->user), // For non-Javascript ACL selector
  493. 'content' => $content,
  494. );
  495. $o .= status_editor($a,$x);
  496. }
  497. // We don't have to deal with ACLs on this page. You're looking at everything
  498. // that belongs to you, hence you can see all of it. We will filter by group if
  499. // desired.
  500. $sql_post_table = "";
  501. $sql_options = (($star) ? " AND `thread`.`starred` " : '');
  502. $sql_options .= (($bmark) ? " AND `thread`.`bookmark` " : '');
  503. $sql_extra = $sql_options;
  504. $sql_extra2 = "";
  505. $sql_extra3 = "";
  506. $sql_table = "`thread`";
  507. $sql_parent = "`iid`";
  508. if ($update) {
  509. $sql_table = "`item`";
  510. $sql_parent = "`parent`";
  511. $sql_post_table = " INNER JOIN `thread` ON `thread`.`iid` = `item`.`parent`";
  512. }
  513. $sql_nets = (($nets) ? sprintf(" and $sql_table.`network` = '%s' ", dbesc($nets)) : '');
  514. if ($group) {
  515. $r = dba::select('group', array('name'), array('id' => $group, 'uid' => $_SESSION['uid']), array('limit' => 1));
  516. if (!dbm::is_result($r)) {
  517. if ($update)
  518. killme();
  519. notice(t('No such group') . EOL);
  520. goaway('network/0');
  521. // NOTREACHED
  522. }
  523. $contacts = expand_groups(array($group));
  524. if ((is_array($contacts)) && count($contacts)) {
  525. $contact_str_self = "";
  526. $contact_str = implode(',',$contacts);
  527. $self = dba::select('contact', array('id'), array('uid' => $_SESSION['uid'], 'self' => true), array('limit' => 1));
  528. if (dbm::is_result($self)) {
  529. $contact_str_self = $self["id"];
  530. }
  531. $sql_post_table .= " INNER JOIN `item` AS `temp1` ON `temp1`.`id` = ".$sql_table.".".$sql_parent;
  532. $sql_extra3 .= " AND (`thread`.`contact-id` IN ($contact_str) ";
  533. $sql_extra3 .= " OR (`thread`.`contact-id` = '$contact_str_self' AND `temp1`.`allow_gid` LIKE '".protect_sprintf('%<'.intval($group).'>%')."' AND `temp1`.`private`))";
  534. } else {
  535. $sql_extra3 .= " AND false ";
  536. info(t('Group is empty'));
  537. }
  538. $o = replace_macros(get_markup_template("section_title.tpl"),array(
  539. '$title' => sprintf(t('Group: %s'), $r['name'])
  540. )) . $o;
  541. } elseif ($cid) {
  542. $fields = array('id', 'name', 'network', 'writable', 'nurl',
  543. 'forum', 'prv', 'contact-type', 'addr', 'thumb', 'location');
  544. $condition = array("`id` = ? AND (NOT `blocked` OR `pending`)", $cid);
  545. $r = dba::select('contact', $fields, $condition, array('limit' => 1));
  546. if (dbm::is_result($r)) {
  547. $sql_extra = " AND ".$sql_table.".`contact-id` = ".intval($cid);
  548. $entries[0] = array(
  549. 'id' => 'network',
  550. 'name' => htmlentities($r['name']),
  551. 'itemurl' => (($r['addr']) ? ($r['addr']) : ($r['nurl'])),
  552. 'thumb' => proxy_url($r['thumb'], false, PROXY_SIZE_THUMB),
  553. 'details' => $r['location'],
  554. );
  555. $entries[0]["account_type"] = account_type($r);
  556. $o = replace_macros(get_markup_template("viewcontact_template.tpl"),array(
  557. 'contacts' => $entries,
  558. 'id' => 'network',
  559. )) . $o;
  560. if ($r['network'] === NETWORK_OSTATUS && $r['writable'] && !PConfig::get(local_user(),'system','nowarn_insecure')) {
  561. notice(t('Private messages to this person are at risk of public disclosure.') . EOL);
  562. }
  563. } else {
  564. notice(t('Invalid contact.') . EOL);
  565. goaway('network');
  566. // NOTREACHED
  567. }
  568. }
  569. if (!$group && !$cid && !$update && !Config::get('theme','hide_eventlist')) {
  570. $o .= get_birthdays();
  571. $o .= get_events();
  572. }
  573. if ($datequery) {
  574. $sql_extra3 .= protect_sprintf(sprintf(" AND $sql_table.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery))));
  575. }
  576. if ($datequery2) {
  577. $sql_extra3 .= protect_sprintf(sprintf(" AND $sql_table.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
  578. }
  579. $sql_order = "";
  580. $order_mode = "received";
  581. if (strlen($file)) {
  582. $sql_post_table .= sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ",
  583. dbesc(protect_sprintf($file)), intval(TERM_OBJ_POST), intval(TERM_FILE), intval(local_user()));
  584. $sql_order = "`item`.`id`";
  585. $order_mode = "id";
  586. }
  587. if ($conv) {
  588. $sql_extra3 .= " AND $sql_table.`mention`";
  589. }
  590. // Normal conversation view
  591. if ($order === 'post') {
  592. $ordering = "`created`";
  593. if ($sql_order == "") {
  594. $order_mode = "created";
  595. }
  596. } else {
  597. $ordering = "`commented`";
  598. if ($sql_order == "") {
  599. $order_mode = "commented";
  600. }
  601. }
  602. if ($sql_order == "") {
  603. $sql_order = "$sql_table.$ordering";
  604. }
  605. if (($_GET["offset"] != "")) {
  606. $sql_extra3 .= sprintf(" AND $sql_order <= '%s'", dbesc($_GET["offset"]));
  607. }
  608. $pager_sql = networkPager($a, $update);
  609. switch ($order_mode) {
  610. case 'received':
  611. if ($last_received != '') {
  612. $sql_extra3 .= sprintf(" AND $sql_table.`received` < '%s'", dbesc($last_received));
  613. $a->set_pager_page(1);
  614. $pager_sql = sprintf(" LIMIT %d, %d ",intval($a->pager['start']), intval($a->pager['itemspage']));
  615. }
  616. break;
  617. case 'commented':
  618. if ($last_commented != '') {
  619. $sql_extra3 .= sprintf(" AND $sql_table.`commented` < '%s'", dbesc($last_commented));
  620. $a->set_pager_page(1);
  621. $pager_sql = sprintf(" LIMIT %d, %d ",intval($a->pager['start']), intval($a->pager['itemspage']));
  622. }
  623. break;
  624. case 'created':
  625. if ($last_created != '') {
  626. $sql_extra3 .= sprintf(" AND $sql_table.`created` < '%s'", dbesc($last_created));
  627. $a->set_pager_page(1);
  628. $pager_sql = sprintf(" LIMIT %d, %d ",intval($a->pager['start']), intval($a->pager['itemspage']));
  629. }
  630. break;
  631. case 'id':
  632. if (($last_id > 0) && ($sql_table == "`thread`")) {
  633. $sql_extra3 .= sprintf(" AND $sql_table.`iid` < '%s'", dbesc($last_id));
  634. $a->set_pager_page(1);
  635. $pager_sql = sprintf(" LIMIT %d, %d ",intval($a->pager['start']), intval($a->pager['itemspage']));
  636. }
  637. break;
  638. }
  639. // Fetch a page full of parent items for this page
  640. if ($update) {
  641. if (Config::get("system", "like_no_comment")) {
  642. $sql_extra4 = " AND `item`.`verb` = '".ACTIVITY_POST."'";
  643. } else {
  644. $sql_extra4 = "";
  645. }
  646. $r = q("SELECT `item`.`parent` AS `item_id`, `item`.`network` AS `item_network`, `contact`.`uid` AS `contact_uid`
  647. FROM $sql_table $sql_post_table INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
  648. AND (NOT `contact`.`blocked` OR `contact`.`pending`)
  649. WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted` $sql_extra4
  650. AND NOT `item`.`moderated` AND `item`.`unseen`
  651. $sql_extra3 $sql_extra $sql_nets
  652. ORDER BY `item_id` DESC LIMIT 100",
  653. intval(local_user())
  654. );
  655. } else {
  656. $r = q("SELECT `thread`.`iid` AS `item_id`, `thread`.`network` AS `item_network`, `contact`.`uid` AS `contact_uid`
  657. FROM $sql_table $sql_post_table STRAIGHT_JOIN `contact` ON `contact`.`id` = `thread`.`contact-id`
  658. AND (NOT `contact`.`blocked` OR `contact`.`pending`)
  659. WHERE `thread`.`uid` = %d AND `thread`.`visible` AND NOT `thread`.`deleted`
  660. AND NOT `thread`.`moderated`
  661. $sql_extra2 $sql_extra3 $sql_extra $sql_nets
  662. ORDER BY $sql_order DESC $pager_sql",
  663. intval(local_user())
  664. );
  665. }
  666. // Then fetch all the children of the parents that are on this page
  667. $parents_arr = array();
  668. $parents_str = '';
  669. $date_offset = "";
  670. if (dbm::is_result($r)) {
  671. foreach ($r as $rr) {
  672. if (!in_array($rr['item_id'],$parents_arr)) {
  673. $parents_arr[] = $rr['item_id'];
  674. }
  675. }
  676. $parents_str = implode(", ", $parents_arr);
  677. // splitted into separate queries to avoid the problem with very long threads
  678. // so always the last X comments are loaded
  679. // This problem can occur expecially with imported facebook posts
  680. $max_comments = Config::get("system", "max_comments");
  681. if ($max_comments == 0) {
  682. $max_comments = 100;
  683. }
  684. $items = array();
  685. foreach ($parents_arr AS $parents) {
  686. $thread_items = dba::p(item_query()." AND `item`.`uid` = ?
  687. AND `item`.`parent` = ?
  688. ORDER BY `item`.`commented` DESC LIMIT ".intval($max_comments + 1),
  689. local_user(),
  690. $parents
  691. );
  692. if (dbm::is_result($thread_items)) {
  693. $items = array_merge($items, dba::inArray($thread_items));
  694. }
  695. }
  696. $items = conv_sort($items,$ordering);
  697. } else {
  698. $items = array();
  699. }
  700. if ($_GET["offset"] == "") {
  701. $date_offset = $items[0][$order_mode];
  702. } else {
  703. $date_offset = $_GET["offset"];
  704. }
  705. $a->page_offset = $date_offset;
  706. // We aren't going to try and figure out at the item, group, and page
  707. // level which items you've seen and which you haven't. If you're looking
  708. // at the top level network page just mark everything seen.
  709. if (!$group && !$cid && !$star) {
  710. $condition = array('unseen' => true, 'uid' => local_user());
  711. networkSetSeen($condition);
  712. } elseif ($parents_str) {
  713. $condition = array("`uid` = ? AND `unseen` AND `parent` IN (" . dbesc($parents_str) . ")", local_user());
  714. networkSetSeen($condition);
  715. }
  716. $mode = 'network';
  717. $o .= networkConversation($a, $items, $mode, $update);
  718. return $o;
  719. }
  720. /**
  721. * @brief Get the network tabs menu
  722. *
  723. * @param App $a The global App
  724. * @return string Html of the networktab
  725. */
  726. function network_tabs(App $a) {
  727. // item filter tabs
  728. /// @TODO fix this logic, reduce duplication
  729. /// $a->page['content'] .= '<div class="tabs-wrapper">';
  730. list($no_active, $all_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active, $spam_active) = network_query_get_sel_tab($a);
  731. // if no tabs are selected, defaults to comments
  732. if ($no_active=='active') $all_active='active';
  733. $cmd = (($datequery) ? '' : $a->cmd);
  734. $len_naked_cmd = strlen(str_replace('/new','',$cmd));
  735. // tabs
  736. $tabs = array(
  737. array(
  738. 'label' => t('Commented Order'),
  739. 'url' => str_replace('/new', '', $cmd) . '?f=&order=comment' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : ''),
  740. 'sel' => $all_active,
  741. 'title' => t('Sort by Comment Date'),
  742. 'id' => 'commented-order-tab',
  743. 'accesskey' => "e",
  744. ),
  745. array(
  746. 'label' => t('Posted Order'),
  747. 'url' => str_replace('/new', '', $cmd) . '?f=&order=post' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : ''),
  748. 'sel' => $postord_active,
  749. 'title' => t('Sort by Post Date'),
  750. 'id' => 'posted-order-tab',
  751. 'accesskey' => "t",
  752. ),
  753. );
  754. if (feature_enabled(local_user(),'personal_tab')) {
  755. $tabs[] = array(
  756. 'label' => t('Personal'),
  757. 'url' => str_replace('/new', '', $cmd) . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&conv=1',
  758. 'sel' => $conv_active,
  759. 'title' => t('Posts that mention or involve you'),
  760. 'id' => 'personal-tab',
  761. 'accesskey' => "r",
  762. );
  763. }
  764. if (feature_enabled(local_user(),'new_tab')) {
  765. $tabs[] = array(
  766. 'label' => t('New'),
  767. 'url' => 'network/new' . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : ''),
  768. 'sel' => $new_active,
  769. 'title' => t('Activity Stream - by date'),
  770. 'id' => 'activitiy-by-date-tab',
  771. 'accesskey' => "w",
  772. );
  773. }
  774. if (feature_enabled(local_user(),'link_tab')) {
  775. $tabs[] = array(
  776. 'label' => t('Shared Links'),
  777. 'url' => str_replace('/new', '', $cmd) . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&bmark=1',
  778. 'sel' => $bookmarked_active,
  779. 'title' => t('Interesting Links'),
  780. 'id' => 'shared-links-tab',
  781. 'accesskey' => "b",
  782. );
  783. }
  784. if (feature_enabled(local_user(),'star_posts')) {
  785. $tabs[] = array(
  786. 'label' => t('Starred'),
  787. 'url' => str_replace('/new', '', $cmd) . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&star=1',
  788. 'sel' => $starred_active,
  789. 'title' => t('Favourite Posts'),
  790. 'id' => 'starred-posts-tab',
  791. 'accesskey' => "m",
  792. );
  793. }
  794. // save selected tab, but only if not in file mode
  795. if (!x($_GET,'file')) {
  796. PConfig::set(local_user(), 'network.view','tab.selected',array($all_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active, $spam_active));
  797. }
  798. $arr = array('tabs' => $tabs);
  799. call_hooks('network_tabs', $arr);
  800. $tpl = get_markup_template('common_tabs.tpl');
  801. return replace_macros($tpl, array('$tabs' => $arr['tabs']));
  802. // --- end item filter tabs
  803. }