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.

899 lines
28 KiB

  1. <?php
  2. // This is a purely experimental module and is not yet generally useful.
  3. // The eventual goal is to provide a json backend to fetch content and fill the current page.
  4. // The page will be filled in on the frontend using javascript.
  5. // At the present time this page is based on "network", but the hope is to extend to serving
  6. // any content (wall, community, search, etc.).
  7. // All search parameters, etc. will be managed in javascript and sent as request params.
  8. // Security will be managed on the backend.
  9. // There is no "pagination query", but we will manage the "current page" on the client
  10. // and provide a link to fetch the next page - until there are no pages left to fetch.
  11. // With the exception of complex tag and text searches, this prototype is incredibly
  12. // fast - e.g. one or two milliseconds to fetch parent items for the current content,
  13. // and 10-20 milliseconds to fetch all the child items.
  14. function content_content(&$a, $update = 0) {
  15. require_once('include/conversation.php');
  16. // Currently security is based on the logged in user
  17. if(! local_user()) {
  18. return;
  19. }
  20. $arr = array('query' => $a->query_string);
  21. call_hooks('content_content_init', $arr);
  22. $datequery = $datequery2 = '';
  23. $group = 0;
  24. $nouveau = false;
  25. if($a->argc > 1) {
  26. for($x = 1; $x < $a->argc; $x ++) {
  27. if(is_a_date_arg($a->argv[$x])) {
  28. if($datequery)
  29. $datequery2 = escape_tags($a->argv[$x]);
  30. else {
  31. $datequery = escape_tags($a->argv[$x]);
  32. $_GET['order'] = 'post';
  33. }
  34. }
  35. elseif($a->argv[$x] === 'new') {
  36. $nouveau = true;
  37. }
  38. elseif(intval($a->argv[$x])) {
  39. $group = intval($a->argv[$x]);
  40. $def_acl = array('allow_gid' => '<' . $group . '>');
  41. }
  42. }
  43. }
  44. $o = '';
  45. $contact_id = $a->cid;
  46. require_once('include/acl_selectors.php');
  47. $cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0);
  48. $star = ((x($_GET,'star')) ? intval($_GET['star']) : 0);
  49. $bmark = ((x($_GET,'bmark')) ? intval($_GET['bmark']) : 0);
  50. $order = ((x($_GET,'order')) ? notags($_GET['order']) : 'comment');
  51. $liked = ((x($_GET,'liked')) ? intval($_GET['liked']) : 0);
  52. $conv = ((x($_GET,'conv')) ? intval($_GET['conv']) : 0);
  53. $spam = ((x($_GET,'spam')) ? intval($_GET['spam']) : 0);
  54. $nets = ((x($_GET,'nets')) ? $_GET['nets'] : '');
  55. $cmin = ((x($_GET,'cmin')) ? intval($_GET['cmin']) : 0);
  56. $cmax = ((x($_GET,'cmax')) ? intval($_GET['cmax']) : 99);
  57. $file = ((x($_GET,'file')) ? $_GET['file'] : '');
  58. if(x($_GET,'search') || x($_GET,'file'))
  59. $nouveau = true;
  60. if($cid)
  61. $def_acl = array('allow_cid' => '<' . intval($cid) . '>');
  62. if($nets) {
  63. $r = q("select id from contact where uid = %d and network = '%s' and self = 0",
  64. intval(local_user()),
  65. dbesc($nets)
  66. );
  67. $str = '';
  68. if(count($r))
  69. foreach($r as $rr)
  70. $str .= '<' . $rr['id'] . '>';
  71. if(strlen($str))
  72. $def_acl = array('allow_cid' => $str);
  73. }
  74. $sql_options = (($star) ? " and starred = 1 " : '');
  75. $sql_options .= (($bmark) ? " and bookmark = 1 " : '');
  76. $sql_nets = (($nets) ? sprintf(" and `contact`.`network` = '%s' ", dbesc($nets)) : '');
  77. $sql_extra = " AND `item`.`parent` IN ( SELECT `parent` FROM `item` WHERE `id` = `parent` $sql_options ) ";
  78. if($group) {
  79. $r = q("SELECT `name`, `id` FROM `group` WHERE `id` = %d AND `uid` = %d LIMIT 1",
  80. intval($group),
  81. intval($_SESSION['uid'])
  82. );
  83. if(! count($r)) {
  84. if($update)
  85. killme();
  86. notice( t('No such group') . EOL );
  87. goaway($a->get_baseurl(true) . '/network');
  88. // NOTREACHED
  89. }
  90. $contacts = expand_groups(array($group));
  91. if((is_array($contacts)) && count($contacts)) {
  92. $contact_str = implode(',',$contacts);
  93. }
  94. else {
  95. $contact_str = ' 0 ';
  96. info( t('Group is empty'));
  97. }
  98. $sql_extra = " AND `item`.`parent` IN ( SELECT DISTINCT(`parent`) FROM `item` WHERE 1 $sql_options AND ( `contact-id` IN ( $contact_str ) OR `allow_gid` like '" . protect_sprintf('%<' . intval($group) . '>%') . "' ) and deleted = 0 ) ";
  99. $o = '<h2>' . t('Group: ') . $r[0]['name'] . '</h2>' . $o;
  100. }
  101. elseif($cid) {
  102. $r = q("SELECT `id`,`name`,`network`,`writable`,`nurl` FROM `contact` WHERE `id` = %d
  103. AND `blocked` = 0 AND `pending` = 0 LIMIT 1",
  104. intval($cid)
  105. );
  106. if(count($r)) {
  107. $sql_extra = " AND `item`.`parent` IN ( SELECT DISTINCT(`parent`) FROM `item` WHERE 1 $sql_options AND `contact-id` = " . intval($cid) . " and deleted = 0 ) ";
  108. }
  109. else {
  110. killme();
  111. }
  112. }
  113. $sql_extra3 = '';
  114. if($datequery) {
  115. $sql_extra3 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery))));
  116. }
  117. if($datequery2) {
  118. $sql_extra3 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
  119. }
  120. $sql_extra2 = (($nouveau) ? '' : " AND `item`.`parent` = `item`.`id` ");
  121. $sql_extra3 = (($nouveau) ? '' : $sql_extra3);
  122. $sql_table = "`item`";
  123. if(x($_GET,'search')) {
  124. $search = escape_tags($_GET['search']);
  125. if(strpos($search,'#') === 0) {
  126. $tag = true;
  127. $search = substr($search,1);
  128. }
  129. if (get_config('system','only_tag_search'))
  130. $tag = true;
  131. if($tag) {
  132. //$sql_extra = sprintf(" AND `term`.`term` = '%s' AND `term`.`otype` = %d AND `term`.`type` = %d ",
  133. // dbesc(protect_sprintf($search)), intval(TERM_OBJ_POST), intval(TERM_HASHTAG));
  134. //$sql_table = "`term` INNER JOIN `item` ON `item`.`id` = `term`.`oid` AND `item`.`uid` = `term`.`uid` ";
  135. $sql_extra = "";
  136. $sql_table = sprintf("`item` 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` ",
  137. dbesc(protect_sprintf($search)), intval(TERM_OBJ_POST), intval(TERM_HASHTAG), intval(local_user()));
  138. } else {
  139. if (get_config('system','use_fulltext_engine'))
  140. $sql_extra = sprintf(" AND MATCH (`item`.`body`, `item`.`title`) AGAINST ('%s' in boolean mode) ", dbesc(protect_sprintf($search)));
  141. else
  142. $sql_extra = sprintf(" AND `item`.`body` REGEXP '%s' ", dbesc(protect_sprintf(preg_quote($search))));
  143. }
  144. }
  145. if(strlen($file)) {
  146. $sql_extra .= file_tag_file_query('item',unxmlify($file));
  147. }
  148. if($conv) {
  149. $myurl = $a->get_baseurl() . '/profile/'. $a->user['nickname'];
  150. $myurl = substr($myurl,strpos($myurl,'://')+3);
  151. $myurl = str_replace('www.','',$myurl);
  152. $diasp_url = str_replace('/profile/','/u/',$myurl);
  153. $sql_extra .= sprintf(" AND `item`.`parent` IN (SELECT distinct(`parent`) from item where `author-link` IN ('https://%s', 'http://%s') OR `mention`)",
  154. dbesc(protect_sprintf($myurl)),
  155. dbesc(protect_sprintf($myurl))
  156. );
  157. }
  158. $pager_sql = sprintf(" LIMIT %d, %d ",intval($a->pager['start']), intval($a->pager['itemspage']));
  159. if($nouveau) {
  160. // "New Item View" - show all items unthreaded in reverse created date order
  161. $items = q("SELECT `item`.*, `item`.`id` AS `item_id`,
  162. `contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`, `contact`.`writable`,
  163. `contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
  164. `contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
  165. FROM $sql_table INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
  166. WHERE `item`.`uid` = %d AND `item`.`visible` = 1
  167. AND `item`.`deleted` = 0 and `item`.`moderated` = 0
  168. $simple_update
  169. AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
  170. $sql_extra $sql_nets
  171. ORDER BY `item`.`received` DESC $pager_sql ",
  172. intval($_SESSION['uid'])
  173. );
  174. }
  175. else {
  176. // Normal conversation view
  177. if($order === 'post')
  178. $ordering = "`created`";
  179. else
  180. $ordering = "`commented`";
  181. $start = dba_timer();
  182. $r = q("SELECT `item`.`id` AS `item_id`, `contact`.`uid` AS `contact_uid`
  183. FROM $sql_table INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
  184. WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0
  185. AND `item`.`moderated` = 0 AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
  186. AND `item`.`parent` = `item`.`id`
  187. $sql_extra3 $sql_extra $sql_nets
  188. ORDER BY `item`.$ordering DESC $pager_sql ",
  189. intval(local_user())
  190. );
  191. $first = dba_timer();
  192. // Then fetch all the children of the parents that are on this page
  193. $parents_arr = array();
  194. $parents_str = '';
  195. if(count($r)) {
  196. foreach($r as $rr)
  197. if(! in_array($rr['item_id'],$parents_arr))
  198. $parents_arr[] = $rr['item_id'];
  199. $parents_str = implode(', ', $parents_arr);
  200. $items = q("SELECT `item`.*, `item`.`id` AS `item_id`,
  201. `contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`alias`, `contact`.`rel`, `contact`.`writable`,
  202. `contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
  203. `contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
  204. FROM $sql_table INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
  205. WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0
  206. AND `item`.`moderated` = 0
  207. AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
  208. AND `item`.`parent` IN ( %s )
  209. $sql_extra ",
  210. intval(local_user()),
  211. dbesc($parents_str)
  212. );
  213. $second = dba_timer();
  214. $items = conv_sort($items,$ordering);
  215. } else {
  216. $items = array();
  217. }
  218. }
  219. logger('parent dba_timer: ' . sprintf('%01.4f',$first - $start));
  220. logger('child dba_timer: ' . sprintf('%01.4f',$second - $first));
  221. // Set this so that the conversation function can find out contact info for our wall-wall items
  222. $a->page_contact = $a->contact;
  223. $mode = (($nouveau) ? 'network-new' : 'network');
  224. $o = render_content($a,$items,$mode,false);
  225. header('Content-type: application/json');
  226. echo json_encode($o);
  227. killme();
  228. }
  229. function render_content(&$a, $items, $mode, $update, $preview = false) {
  230. require_once('include/bbcode.php');
  231. require_once('mod/proxy.php');
  232. $ssl_state = ((local_user()) ? true : false);
  233. $profile_owner = 0;
  234. $page_writeable = false;
  235. $previewing = (($preview) ? ' preview ' : '');
  236. if($mode === 'network') {
  237. $profile_owner = local_user();
  238. $page_writeable = true;
  239. }
  240. if($mode === 'profile') {
  241. $profile_owner = $a->profile['profile_uid'];
  242. $page_writeable = can_write_wall($a,$profile_owner);
  243. }
  244. if($mode === 'notes') {
  245. $profile_owner = local_user();
  246. $page_writeable = true;
  247. }
  248. if($mode === 'display') {
  249. $profile_owner = $a->profile['uid'];
  250. $page_writeable = can_write_wall($a,$profile_owner);
  251. }
  252. if($mode === 'community') {
  253. $profile_owner = 0;
  254. $page_writeable = false;
  255. }
  256. if($update)
  257. $return_url = $_SESSION['return_url'];
  258. else
  259. $return_url = $_SESSION['return_url'] = $a->query_string;
  260. load_contact_links(local_user());
  261. $cb = array('items' => $items, 'mode' => $mode, 'update' => $update, 'preview' => $preview);
  262. call_hooks('conversation_start',$cb);
  263. $items = $cb['items'];
  264. $cmnt_tpl = get_markup_template('comment_item.tpl');
  265. $tpl = 'wall_item.tpl';
  266. $wallwall = 'wallwall_item.tpl';
  267. $hide_comments_tpl = get_markup_template('hide_comments.tpl');
  268. $alike = array();
  269. $dlike = array();
  270. // array with html for each thread (parent+comments)
  271. $threads = array();
  272. $threadsid = -1;
  273. if($items && count($items)) {
  274. if($mode === 'network-new' || $mode === 'search' || $mode === 'community') {
  275. // "New Item View" on network page or search page results
  276. // - just loop through the items and format them minimally for display
  277. //$tpl = get_markup_template('search_item.tpl');
  278. $tpl = 'search_item.tpl';
  279. foreach($items as $item) {
  280. $threadsid++;
  281. $comment = '';
  282. $owner_url = '';
  283. $owner_photo = '';
  284. $owner_name = '';
  285. $sparkle = '';
  286. if($mode === 'search' || $mode === 'community') {
  287. if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE)))
  288. && ($item['id'] != $item['parent']))
  289. continue;
  290. $nickname = $item['nickname'];
  291. }
  292. else
  293. $nickname = $a->user['nickname'];
  294. // prevent private email from leaking.
  295. if($item['network'] === NETWORK_MAIL && local_user() != $item['uid'])
  296. continue;
  297. $profile_name = ((strlen($item['author-name'])) ? $item['author-name'] : $item['name']);
  298. if($item['author-link'] && (! $item['author-name']))
  299. $profile_name = $item['author-link'];
  300. $sp = false;
  301. $profile_link = best_link_url($item,$sp);
  302. if($profile_link === 'mailbox')
  303. $profile_link = '';
  304. if($sp)
  305. $sparkle = ' sparkle';
  306. else
  307. $profile_link = zrl($profile_link);
  308. $normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']);
  309. if(($normalised != 'mailbox') && (x($a->contacts[$normalised])))
  310. $profile_avatar = $a->contacts[$normalised]['thumb'];
  311. else
  312. $profile_avatar = ((strlen($item['author-avatar'])) ? $a->get_cached_avatar_image($item['author-avatar']) : $item['thumb']);
  313. $locate = array('location' => $item['location'], 'coord' => $item['coord'], 'html' => '');
  314. call_hooks('render_location',$locate);
  315. $location = ((strlen($locate['html'])) ? $locate['html'] : render_location_google($locate));
  316. localize_item($item);
  317. if($mode === 'network-new')
  318. $dropping = true;
  319. else
  320. $dropping = false;
  321. $drop = array(
  322. 'dropping' => $dropping,
  323. 'select' => t('Select'),
  324. 'delete' => t('Delete'),
  325. );
  326. $star = false;
  327. $isstarred = "unstarred";
  328. $lock = false;
  329. $likebuttons = false;
  330. $shareable = false;
  331. $body = prepare_body($item,true);
  332. if($a->theme['template_engine'] === 'internal') {
  333. $name_e = template_escape($profile_name);
  334. $title_e = template_escape($item['title']);
  335. $body_e = template_escape($body);
  336. $text_e = strip_tags(template_escape($body));
  337. $location_e = template_escape($location);
  338. $owner_name_e = template_escape($owner_name);
  339. }
  340. else {
  341. $name_e = $profile_name;
  342. $title_e = $item['title'];
  343. $body_e = $body;
  344. $text_e = strip_tags($body);
  345. $location_e = $location;
  346. $owner_name_e = $owner_name;
  347. }
  348. //$tmp_item = replace_macros($tpl,array(
  349. $tmp_item = array(
  350. 'template' => $tpl,
  351. 'id' => (($preview) ? 'P0' : $item['item_id']),
  352. 'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])),
  353. 'profile_url' => $profile_link,
  354. 'item_photo_menu' => item_photo_menu($item),
  355. 'name' => $name_e,
  356. 'sparkle' => $sparkle,
  357. 'lock' => $lock,
  358. 'thumb' => proxy_url($profile_avatar),
  359. 'title' => $title_e,
  360. 'body' => $body_e,
  361. 'text' => $text_e,
  362. 'ago' => (($item['app']) ? sprintf( t('%s from %s'),relative_date($item['created']),$item['app']) : relative_date($item['created'])),
  363. 'location' => $location_e,
  364. 'indent' => '',
  365. 'owner_name' => $owner_name_e,
  366. 'owner_url' => $owner_url,
  367. 'owner_photo' => proxy_url($owner_photo),
  368. 'plink' => get_plink($item),
  369. 'edpost' => false,
  370. 'isstarred' => $isstarred,
  371. 'star' => $star,
  372. 'drop' => $drop,
  373. 'vote' => $likebuttons,
  374. 'like' => '',
  375. 'dislike' => '',
  376. 'comment' => '',
  377. //'conv' => (($preview) ? '' : array('href'=> $a->get_baseurl($ssl_state) . '/display/' . $nickname . '/' . $item['id'], 'title'=> t('View in context'))),
  378. 'conv' => (($preview) ? '' : array('href'=> $a->get_baseurl($ssl_state).'/display/'.$item['guid'], 'title'=> t('View in context'))),
  379. 'previewing' => $previewing,
  380. 'wait' => t('Please wait'),
  381. );
  382. $arr = array('item' => $item, 'output' => $tmp_item);
  383. call_hooks('display_item', $arr);
  384. $threads[$threadsid]['id'] = $item['item_id'];
  385. $threads[$threadsid]['items'] = array($arr['output']);
  386. }
  387. }
  388. else
  389. {
  390. // Normal View
  391. // Figure out how many comments each parent has
  392. // (Comments all have gravity of 6)
  393. // Store the result in the $comments array
  394. $comments = array();
  395. foreach($items as $item) {
  396. if((intval($item['gravity']) == 6) && ($item['id'] != $item['parent'])) {
  397. if(! x($comments,$item['parent']))
  398. $comments[$item['parent']] = 1;
  399. else
  400. $comments[$item['parent']] += 1;
  401. } elseif(! x($comments,$item['parent']))
  402. $comments[$item['parent']] = 0; // avoid notices later on
  403. }
  404. // map all the like/dislike activities for each parent item
  405. // Store these in the $alike and $dlike arrays
  406. foreach($items as $item) {
  407. like_puller($a,$item,$alike,'like');
  408. like_puller($a,$item,$dlike,'dislike');
  409. }
  410. $comments_collapsed = false;
  411. $comments_seen = 0;
  412. $comment_lastcollapsed = false;
  413. $comment_firstcollapsed = false;
  414. $blowhard = 0;
  415. $blowhard_count = 0;
  416. foreach($items as $item) {
  417. $comment = '';
  418. $template = $tpl;
  419. $commentww = '';
  420. $sparkle = '';
  421. $owner_url = $owner_photo = $owner_name = '';
  422. // We've already parsed out like/dislike for special treatment. We can ignore them now
  423. if(((activity_match($item['verb'],ACTIVITY_LIKE))
  424. || (activity_match($item['verb'],ACTIVITY_DISLIKE)))
  425. && ($item['id'] != $item['parent']))
  426. continue;
  427. $toplevelpost = (($item['id'] == $item['parent']) ? true : false);
  428. // Take care of author collapsing and comment collapsing
  429. // (author collapsing is currently disabled)
  430. // If a single author has more than 3 consecutive top-level posts, squash the remaining ones.
  431. // If there are more than two comments, squash all but the last 2.
  432. if($toplevelpost) {
  433. $item_writeable = (($item['writable'] || $item['self']) ? true : false);
  434. $comments_seen = 0;
  435. $comments_collapsed = false;
  436. $comment_lastcollapsed = false;
  437. $comment_firstcollapsed = false;
  438. $threadsid++;
  439. $threads[$threadsid]['id'] = $item['item_id'];
  440. $threads[$threadsid]['private'] = $item['private'];
  441. $threads[$threadsid]['items'] = array();
  442. }
  443. else {
  444. // prevent private email reply to public conversation from leaking.
  445. if($item['network'] === NETWORK_MAIL && local_user() != $item['uid'])
  446. continue;
  447. $comments_seen ++;
  448. $comment_lastcollapsed = false;
  449. $comment_firstcollapsed = false;
  450. }
  451. $override_comment_box = ((($page_writeable) && ($item_writeable)) ? true : false);
  452. $show_comment_box = ((($page_writeable) && ($item_writeable) && ($comments_seen == $comments[$item['parent']])) ? true : false);
  453. if(($comments[$item['parent']] > 2) && ($comments_seen <= ($comments[$item['parent']] - 2)) && ($item['gravity'] == 6)) {
  454. if (!$comments_collapsed){
  455. $threads[$threadsid]['num_comments'] = sprintf( tt('%d comment','%d comments',$comments[$item['parent']]),$comments[$item['parent']] );
  456. $threads[$threadsid]['hidden_comments_num'] = $comments[$item['parent']];
  457. $threads[$threadsid]['hidden_comments_text'] = tt('comment', 'comments', $comments[$item['parent']]);
  458. $threads[$threadsid]['hide_text'] = t('show more');
  459. $comments_collapsed = true;
  460. $comment_firstcollapsed = true;
  461. }
  462. }
  463. if(($comments[$item['parent']] > 2) && ($comments_seen == ($comments[$item['parent']] - 1))) {
  464. $comment_lastcollapsed = true;
  465. }
  466. $redirect_url = $a->get_baseurl($ssl_state) . '/redir/' . $item['cid'] ;
  467. $lock = ((($item['private'] == 1) || (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
  468. || strlen($item['deny_cid']) || strlen($item['deny_gid']))))
  469. ? t('Private Message')
  470. : false);
  471. // Top-level wall post not written by the wall owner (wall-to-wall)
  472. // First figure out who owns it.
  473. $osparkle = '';
  474. if(($toplevelpost) && (! $item['self']) && ($mode !== 'profile')) {
  475. if($item['wall']) {
  476. // On the network page, I am the owner. On the display page it will be the profile owner.
  477. // This will have been stored in $a->page_contact by our calling page.
  478. // Put this person as the wall owner of the wall-to-wall notice.
  479. $owner_url = zrl($a->page_contact['url']);
  480. $owner_photo = $a->page_contact['thumb'];
  481. $owner_name = $a->page_contact['name'];
  482. $template = $wallwall;
  483. $commentww = 'ww';
  484. }
  485. if((! $item['wall']) && $item['owner-link']) {
  486. $owner_linkmatch = (($item['owner-link']) && link_compare($item['owner-link'],$item['author-link']));
  487. $alias_linkmatch = (($item['alias']) && link_compare($item['alias'],$item['author-link']));
  488. $owner_namematch = (($item['owner-name']) && $item['owner-name'] == $item['author-name']);
  489. if((! $owner_linkmatch) && (! $alias_linkmatch) && (! $owner_namematch)) {
  490. // The author url doesn't match the owner (typically the contact)
  491. // and also doesn't match the contact alias.
  492. // The name match is a hack to catch several weird cases where URLs are
  493. // all over the park. It can be tricked, but this prevents you from
  494. // seeing "Bob Smith to Bob Smith via Wall-to-wall" and you know darn
  495. // well that it's the same Bob Smith.
  496. // But it could be somebody else with the same name. It just isn't highly likely.
  497. $owner_url = $item['owner-link'];
  498. $owner_photo = $item['owner-avatar'];
  499. $owner_name = $item['owner-name'];
  500. $template = $wallwall;
  501. $commentww = 'ww';
  502. // If it is our contact, use a friendly redirect link
  503. if((link_compare($item['owner-link'],$item['url']))
  504. && ($item['network'] === NETWORK_DFRN)) {
  505. $owner_url = $redirect_url;
  506. $osparkle = ' sparkle';
  507. }
  508. else
  509. $owner_url = zrl($owner_url);
  510. }
  511. }
  512. }
  513. $likebuttons = '';
  514. $shareable = ((($profile_owner == local_user()) && ($item['private'] != 1)) ? true : false);
  515. if($page_writeable) {
  516. /* if($toplevelpost) { */
  517. $likebuttons = array(
  518. 'like' => array( t("I like this \x28toggle\x29"), t("like")),
  519. 'dislike' => array( t("I don't like this \x28toggle\x29"), t("dislike")),
  520. );
  521. if ($shareable) $likebuttons['share'] = array( t('Share this'), t('share'));
  522. /* } */
  523. $qc = $qcomment = null;
  524. if(in_array('qcomment',$a->plugins)) {
  525. $qc = ((local_user()) ? get_pconfig(local_user(),'qcomment','words') : null);
  526. $qcomment = (($qc) ? explode("\n",$qc) : null);
  527. }
  528. if(($show_comment_box) || (($show_comment_box == false) && ($override_comment_box == false) && ($item['last-child']))) {
  529. $comment = replace_macros($cmnt_tpl,array(
  530. '$return_path' => '',
  531. '$jsreload' => (($mode === 'display') ? $_SESSION['return_url'] : ''),
  532. '$type' => (($mode === 'profile') ? 'wall-comment' : 'net-comment'),
  533. '$id' => $item['item_id'],
  534. '$parent' => $item['parent'],
  535. '$qcomment' => $qcomment,
  536. '$profile_uid' => $profile_owner,
  537. '$mylink' => $a->contact['url'],
  538. '$mytitle' => t('This is you'),
  539. '$myphoto' => $a->contact['thumb'],
  540. '$comment' => t('Comment'),
  541. '$submit' => t('Submit'),
  542. '$edbold' => t('Bold'),
  543. '$editalic' => t('Italic'),
  544. '$eduline' => t('Underline'),
  545. '$edquote' => t('Quote'),
  546. '$edcode' => t('Code'),
  547. '$edimg' => t('Image'),
  548. '$edurl' => t('Link'),
  549. '$edvideo' => t('Video'),
  550. '$preview' => t('Preview'),
  551. '$sourceapp' => t($a->sourcename),
  552. '$ww' => (($mode === 'network') ? $commentww : ''),
  553. '$rand_num' => random_digits(12)
  554. ));
  555. }
  556. }
  557. if(local_user() && link_compare($a->contact['url'],$item['author-link']))
  558. $edpost = array($a->get_baseurl($ssl_state)."/editpost/".$item['id'], t("Edit"));
  559. else
  560. $edpost = false;
  561. $drop = '';
  562. $dropping = false;
  563. if((intval($item['contact-id']) && $item['contact-id'] == remote_user()) || ($item['uid'] == local_user()))
  564. $dropping = true;
  565. $drop = array(
  566. 'dropping' => $dropping,
  567. 'select' => t('Select'),
  568. 'delete' => t('Delete'),
  569. );
  570. $star = false;
  571. $filer = false;
  572. $isstarred = "unstarred";
  573. if ($profile_owner == local_user()) {
  574. if($toplevelpost) {
  575. $isstarred = (($item['starred']) ? "starred" : "unstarred");
  576. $star = array(
  577. 'do' => t("add star"),
  578. 'undo' => t("remove star"),
  579. 'toggle' => t("toggle star status"),
  580. 'classdo' => (($item['starred']) ? "hidden" : ""),
  581. 'classundo' => (($item['starred']) ? "" : "hidden"),
  582. 'starred' => t('starred'),
  583. 'tagger' => t("add tag"),
  584. 'classtagger' => "",
  585. );
  586. }
  587. $filer = t("save to folder");
  588. }
  589. $photo = $item['photo'];
  590. $thumb = $item['thumb'];
  591. // Post was remotely authored.
  592. $diff_author = ((link_compare($item['url'],$item['author-link'])) ? false : true);
  593. $profile_name = (((strlen($item['author-name'])) && $diff_author) ? $item['author-name'] : $item['name']);
  594. if($item['author-link'] && (! $item['author-name']))
  595. $profile_name = $item['author-link'];
  596. $sp = false;
  597. $profile_link = best_link_url($item,$sp);
  598. if($profile_link === 'mailbox')
  599. $profile_link = '';
  600. if($sp)
  601. $sparkle = ' sparkle';
  602. else
  603. $profile_link = zrl($profile_link);
  604. $normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']);
  605. if(($normalised != 'mailbox') && (x($a->contacts,$normalised)))
  606. $profile_avatar = $a->contacts[$normalised]['thumb'];
  607. else
  608. $profile_avatar = (((strlen($item['author-avatar'])) && $diff_author) ? $item['author-avatar'] : $a->get_cached_avatar_image($thumb));
  609. $like = ((x($alike,$item['uri'])) ? format_like($alike[$item['uri']],$alike[$item['uri'] . '-l'],'like',$item['uri']) : '');
  610. $dislike = ((x($dlike,$item['uri'])) ? format_like($dlike[$item['uri']],$dlike[$item['uri'] . '-l'],'dislike',$item['uri']) : '');
  611. $locate = array('location' => $item['location'], 'coord' => $item['coord'], 'html' => '');
  612. call_hooks('render_location',$locate);
  613. $location = ((strlen($locate['html'])) ? $locate['html'] : render_location_google($locate));
  614. $indent = (($toplevelpost) ? '' : ' comment');
  615. $shiny = "";
  616. if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
  617. $shiny = 'shiny';
  618. //
  619. localize_item($item);
  620. $tags=array();
  621. foreach(explode(',',$item['tag']) as $tag){
  622. $tag = trim($tag);
  623. if ($tag!="") $tags[] = bbcode($tag);
  624. }
  625. // Build the HTML
  626. $body = prepare_body($item,true);
  627. //$tmp_item = replace_macros($template,
  628. if($a->theme['template_engine'] === 'internal') {
  629. $body_e = template_escape($body);
  630. $text_e = strip_tags(template_escape($body));
  631. $name_e = template_escape($profile_name);
  632. $title_e = template_escape($item['title']);
  633. $location_e = template_escape($location);
  634. $owner_name_e = template_escape($owner_name);
  635. }
  636. else {
  637. $body_e = $body;
  638. $text_e = strip_tags($body);
  639. $name_e = $profile_name;
  640. $title_e = $item['title'];
  641. $location_e = $location;
  642. $owner_name_e = $owner_name;
  643. }
  644. $tmp_item = array(
  645. // collapse comments in template. I don't like this much...
  646. 'comment_firstcollapsed' => $comment_firstcollapsed,
  647. 'comment_lastcollapsed' => $comment_lastcollapsed,
  648. // template to use to render item (wall, walltowall, search)
  649. 'template' => $template,
  650. 'type' => implode("",array_slice(explode("/",$item['verb']),-1)),
  651. 'tags' => $tags,
  652. 'body' => $body_e,
  653. 'text' => $text_e,
  654. 'id' => $item['item_id'],
  655. 'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])),
  656. 'olinktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['owner-link'])) ? $item['owner-link'] : $item['url'])),
  657. 'to' => t('to'),
  658. 'wall' => t('Wall-to-Wall'),
  659. 'vwall' => t('via Wall-To-Wall:'),
  660. 'profile_url' => $profile_link,
  661. 'item_photo_menu' => item_photo_menu($item),
  662. 'name' => $name_e,
  663. 'thumb' => proxy_url($profile_avatar),
  664. 'osparkle' => $osparkle,
  665. 'sparkle' => $sparkle,
  666. 'title' => $title_e,
  667. 'ago' => (($item['app']) ? sprintf( t('%s from %s'),relative_date($item['created']),$item['app']) : relative_date($item['created'])),
  668. 'lock' => $lock,
  669. 'location' => $location_e,
  670. 'indent' => $indent,
  671. 'shiny' => $shiny,
  672. 'owner_url' => $owner_url,
  673. 'owner_photo' => proxy_url($owner_photo),
  674. 'owner_name' => $owner_name_e,
  675. 'plink' => get_plink($item),
  676. 'edpost' => $edpost,
  677. 'isstarred' => $isstarred,
  678. 'star' => $star,
  679. 'filer' => $filer,
  680. 'drop' => $drop,
  681. 'vote' => $likebuttons,
  682. 'like' => $like,
  683. 'dislike' => $dislike,
  684. 'comment' => $comment,
  685. 'previewing' => $previewing,
  686. 'wait' => t('Please wait'),
  687. );
  688. $arr = array('item' => $item, 'output' => $tmp_item);
  689. call_hooks('display_item', $arr);
  690. $threads[$threadsid]['items'][] = $arr['output'];
  691. }
  692. }
  693. }
  694. return $threads;
  695. }