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.

1340 lines
40 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. <?php
  2. // Note: the code in 'item_extract_images' and 'item_redir_and_replace_images'
  3. // is identical to the code in mod/message.php for 'item_extract_images' and
  4. // 'item_redir_and_replace_images'
  5. if(! function_exists('item_extract_images')) {
  6. function item_extract_images($body) {
  7. $saved_image = array();
  8. $orig_body = $body;
  9. $new_body = '';
  10. $cnt = 0;
  11. $img_start = strpos($orig_body, '[img');
  12. $img_st_close = ($img_start !== false ? strpos(substr($orig_body, $img_start), ']') : false);
  13. $img_end = ($img_start !== false ? strpos(substr($orig_body, $img_start), '[/img]') : false);
  14. while(($img_st_close !== false) && ($img_end !== false)) {
  15. $img_st_close++; // make it point to AFTER the closing bracket
  16. $img_end += $img_start;
  17. if(! strcmp(substr($orig_body, $img_start + $img_st_close, 5), 'data:')) {
  18. // This is an embedded image
  19. $saved_image[$cnt] = substr($orig_body, $img_start + $img_st_close, $img_end - ($img_start + $img_st_close));
  20. $new_body = $new_body . substr($orig_body, 0, $img_start) . '[!#saved_image' . $cnt . '#!]';
  21. $cnt++;
  22. }
  23. else
  24. $new_body = $new_body . substr($orig_body, 0, $img_end + strlen('[/img]'));
  25. $orig_body = substr($orig_body, $img_end + strlen('[/img]'));
  26. if($orig_body === false) // in case the body ends on a closing image tag
  27. $orig_body = '';
  28. $img_start = strpos($orig_body, '[img');
  29. $img_st_close = ($img_start !== false ? strpos(substr($orig_body, $img_start), ']') : false);
  30. $img_end = ($img_start !== false ? strpos(substr($orig_body, $img_start), '[/img]') : false);
  31. }
  32. $new_body = $new_body . $orig_body;
  33. return array('body' => $new_body, 'images' => $saved_image);
  34. }}
  35. if(! function_exists('item_redir_and_replace_images')) {
  36. function item_redir_and_replace_images($body, $images, $cid) {
  37. $origbody = $body;
  38. $newbody = '';
  39. for($i = 0; $i < count($images); $i++) {
  40. $search = '/\[url\=(.*?)\]\[!#saved_image' . $i . '#!\]\[\/url\]' . '/is';
  41. $replace = '[url=' . z_path() . '/redir/' . $cid
  42. . '?f=1&url=' . '$1' . '][!#saved_image' . $i . '#!][/url]' ;
  43. $img_end = strpos($origbody, '[!#saved_image' . $i . '#!][/url]') + strlen('[!#saved_image' . $i . '#!][/url]');
  44. $process_part = substr($origbody, 0, $img_end);
  45. $origbody = substr($origbody, $img_end);
  46. $process_part = preg_replace($search, $replace, $process_part);
  47. $newbody = $newbody . $process_part;
  48. }
  49. $newbody = $newbody . $origbody;
  50. $cnt = 0;
  51. foreach($images as $image) {
  52. // We're depending on the property of 'foreach' (specified on the PHP website) that
  53. // it loops over the array starting from the first element and going sequentially
  54. // to the last element
  55. $newbody = str_replace('[!#saved_image' . $cnt . '#!]', '[img]' . $image . '[/img]', $newbody);
  56. $cnt++;
  57. }
  58. return $newbody;
  59. }}
  60. /**
  61. * Render actions localized
  62. */
  63. function localize_item(&$item){
  64. $extracted = item_extract_images($item['body']);
  65. if($extracted['images'])
  66. $item['body'] = item_redir_and_replace_images($extracted['body'], $extracted['images'], $item['contact-id']);
  67. $xmlhead="<"."?xml version='1.0' encoding='UTF-8' ?".">";
  68. if ($item['verb']=== ACTIVITY_LIKE || $item['verb']=== ACTIVITY_DISLIKE){
  69. $r = q("SELECT * from `item`,`contact` WHERE
  70. `item`.`contact-id`=`contact`.`id` AND `item`.`uri`='%s';",
  71. dbesc($item['parent-uri']));
  72. if(count($r)==0) return;
  73. $obj=$r[0];
  74. $author = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]';
  75. $objauthor = '[url=' . $obj['author-link'] . ']' . $obj['author-name'] . '[/url]';
  76. switch($obj['verb']){
  77. case ACTIVITY_POST:
  78. switch ($obj['object-type']){
  79. case ACTIVITY_OBJ_EVENT:
  80. $post_type = t('event');
  81. break;
  82. default:
  83. $post_type = t('status');
  84. }
  85. break;
  86. default:
  87. if($obj['resource-id']){
  88. $post_type = t('photo');
  89. $m=array(); preg_match("/\[url=([^]]*)\]/", $obj['body'], $m);
  90. $rr['plink'] = $m[1];
  91. } else {
  92. $post_type = t('status');
  93. }
  94. }
  95. $plink = '[url=' . $obj['plink'] . ']' . $post_type . '[/url]';
  96. switch($item['verb']){
  97. case ACTIVITY_LIKE :
  98. $bodyverb = t('%1$s likes %2$s\'s %3$s');
  99. break;
  100. case ACTIVITY_DISLIKE:
  101. $bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s');
  102. break;
  103. }
  104. $item['body'] = sprintf($bodyverb, $author, $objauthor, $plink);
  105. }
  106. if ($item['verb']=== ACTIVITY_FRIEND){
  107. if ($item['object-type']=="" || $item['object-type']!== ACTIVITY_OBJ_PERSON) return;
  108. $Aname = $item['author-name'];
  109. $Alink = $item['author-link'];
  110. $xmlhead="<"."?xml version='1.0' encoding='UTF-8' ?".">";
  111. $obj = parse_xml_string($xmlhead.$item['object']);
  112. $links = parse_xml_string($xmlhead."<links>".unxmlify($obj->link)."</links>");
  113. $Bname = $obj->title;
  114. $Blink = ""; $Bphoto = "";
  115. foreach ($links->link as $l){
  116. $atts = $l->attributes();
  117. switch($atts['rel']){
  118. case "alternate": $Blink = $atts['href'];
  119. case "photo": $Bphoto = $atts['href'];
  120. }
  121. }
  122. $A = '[url=' . zrl($Alink) . ']' . $Aname . '[/url]';
  123. $B = '[url=' . zrl($Blink) . ']' . $Bname . '[/url]';
  124. if ($Bphoto!="") $Bphoto = '[url=' . zrl($Blink) . '][img]' . $Bphoto . '[/img][/url]';
  125. $item['body'] = sprintf( t('%1$s is now friends with %2$s'), $A, $B)."\n\n\n".$Bphoto;
  126. }
  127. if (stristr($item['verb'],ACTIVITY_POKE)) {
  128. $verb = urldecode(substr($item['verb'],strpos($item['verb'],'#')+1));
  129. if(! $verb)
  130. return;
  131. if ($item['object-type']=="" || $item['object-type']!== ACTIVITY_OBJ_PERSON) return;
  132. $Aname = $item['author-name'];
  133. $Alink = $item['author-link'];
  134. $xmlhead="<"."?xml version='1.0' encoding='UTF-8' ?".">";
  135. $obj = parse_xml_string($xmlhead.$item['object']);
  136. $links = parse_xml_string($xmlhead."<links>".unxmlify($obj->link)."</links>");
  137. $Bname = $obj->title;
  138. $Blink = ""; $Bphoto = "";
  139. foreach ($links->link as $l){
  140. $atts = $l->attributes();
  141. switch($atts['rel']){
  142. case "alternate": $Blink = $atts['href'];
  143. case "photo": $Bphoto = $atts['href'];
  144. }
  145. }
  146. $A = '[url=' . zrl($Alink) . ']' . $Aname . '[/url]';
  147. $B = '[url=' . zrl($Blink) . ']' . $Bname . '[/url]';
  148. if ($Bphoto!="") $Bphoto = '[url=' . zrl($Blink) . '][img=80x80]' . $Bphoto . '[/img][/url]';
  149. // we can't have a translation string with three positions but no distinguishable text
  150. // So here is the translate string.
  151. $txt = t('%1$s poked %2$s');
  152. // now translate the verb
  153. $txt = str_replace( t('poked'), t($verb), $txt);
  154. // then do the sprintf on the translation string
  155. $item['body'] = sprintf($txt, $A, $B). "\n\n\n" . $Bphoto;
  156. }
  157. if (stristr($item['verb'],ACTIVITY_MOOD)) {
  158. $verb = urldecode(substr($item['verb'],strpos($item['verb'],'#')+1));
  159. if(! $verb)
  160. return;
  161. $Aname = $item['author-name'];
  162. $Alink = $item['author-link'];
  163. $A = '[url=' . zrl($Alink) . ']' . $Aname . '[/url]';
  164. $txt = t('%1$s is currently %2$s');
  165. $item['body'] = sprintf($txt, $A, t($verb));
  166. }
  167. if ($item['verb']===ACTIVITY_TAG){
  168. $r = q("SELECT * from `item`,`contact` WHERE
  169. `item`.`contact-id`=`contact`.`id` AND `item`.`uri`='%s';",
  170. dbesc($item['parent-uri']));
  171. if(count($r)==0) return;
  172. $obj=$r[0];
  173. $author = '[url=' . zrl($item['author-link']) . ']' . $item['author-name'] . '[/url]';
  174. $objauthor = '[url=' . zrl($obj['author-link']) . ']' . $obj['author-name'] . '[/url]';
  175. switch($obj['verb']){
  176. case ACTIVITY_POST:
  177. switch ($obj['object-type']){
  178. case ACTIVITY_OBJ_EVENT:
  179. $post_type = t('event');
  180. break;
  181. default:
  182. $post_type = t('status');
  183. }
  184. break;
  185. default:
  186. if($obj['resource-id']){
  187. $post_type = t('photo');
  188. $m=array(); preg_match("/\[url=([^]]*)\]/", $obj['body'], $m);
  189. $rr['plink'] = $m[1];
  190. } else {
  191. $post_type = t('status');
  192. }
  193. }
  194. $plink = '[url=' . $obj['plink'] . ']' . $post_type . '[/url]';
  195. $parsedobj = parse_xml_string($xmlhead.$item['object']);
  196. $tag = sprintf('#[url=%s]%s[/url]', $parsedobj->id, $parsedobj->content);
  197. $item['body'] = sprintf( t('%1$s tagged %2$s\'s %3$s with %4$s'), $author, $objauthor, $plink, $tag );
  198. }
  199. if ($item['verb']=== ACTIVITY_FAVORITE){
  200. if ($item['object-type']== "")
  201. return;
  202. $Aname = $item['author-name'];
  203. $Alink = $item['author-link'];
  204. $xmlhead="<"."?xml version='1.0' encoding='UTF-8' ?".">";
  205. $obj = parse_xml_string($xmlhead.$item['object']);
  206. if(strlen($obj->id)) {
  207. $r = q("select * from item where uri = '%s' and uid = %d limit 1",
  208. dbesc($obj->id),
  209. intval($item['uid'])
  210. );
  211. if(count($r) && $r[0]['plink']) {
  212. $target = $r[0];
  213. $Bname = $target['author-name'];
  214. $Blink = $target['author-link'];
  215. $A = '[url=' . zrl($Alink) . ']' . $Aname . '[/url]';
  216. $B = '[url=' . zrl($Blink) . ']' . $Bname . '[/url]';
  217. $P = '[url=' . $target['plink'] . ']' . t('post/item') . '[/url]';
  218. $item['body'] = sprintf( t('%1$s marked %2$s\'s %3$s as favorite'), $A, $B, $P)."\n";
  219. }
  220. }
  221. }
  222. $matches = null;
  223. if(preg_match_all('/@\[url=(.*?)\]/is',$item['body'],$matches,PREG_SET_ORDER)) {
  224. foreach($matches as $mtch) {
  225. if(! strpos($mtch[1],'zrl='))
  226. $item['body'] = str_replace($mtch[0],'@[url=' . zrl($mtch[1]). ']',$item['body']);
  227. }
  228. }
  229. // add zrl's to public images
  230. if(preg_match_all('/\[url=(.*?)\/photos\/(.*?)\/image\/(.*?)\]\[img(.*?)\]h(.*?)\[\/img\]\[\/url\]/is',$item['body'],$matches,PREG_SET_ORDER)) {
  231. foreach($matches as $mtch) {
  232. $item['body'] = str_replace($mtch[0],'[url=' . zrl($mtch[1] . '/photos/' . $mtch[2] . '/image/' . $mtch[3] ,true) . '][img' . $mtch[4] . ']h' . $mtch[5] . '[/img][/url]',$item['body']);
  233. }
  234. }
  235. // add sparkle links to appropriate permalinks
  236. $x = stristr($item['plink'],'/display/');
  237. if($x) {
  238. $sparkle = false;
  239. $y = best_link_url($item,$sparkle,true);
  240. if(strstr($y,'/redir/'))
  241. $item['plink'] = $y . '?f=&url=' . $item['plink'];
  242. }
  243. }
  244. /**
  245. * Count the total of comments on this item and its desendants
  246. */
  247. function count_descendants($item) {
  248. $total = count($item['children']);
  249. if($total > 0) {
  250. foreach($item['children'] as $child) {
  251. if($child['verb'] === ACTIVITY_LIKE || $child['verb'] === ACTIVITY_DISLIKE) {
  252. $total --;
  253. }
  254. $total += count_descendants($child);
  255. }
  256. }
  257. return $total;
  258. }
  259. /**
  260. * Recursively prepare a thread for HTML
  261. */
  262. function prepare_threads_body($a, $items, $cmnt_tpl, $page_writeable, $mode, $profile_owner, $alike, $dlike, $thread_level=1) {
  263. $result = array();
  264. $wall_template = 'wall_thread.tpl';
  265. $wallwall_template = 'wallwall_thread.tpl';
  266. $items_seen = 0;
  267. $nb_items = count($items);
  268. $total_children = $nb_items;
  269. foreach($items as $item) {
  270. if($item['network'] === NETWORK_MAIL && local_user() != $item['uid']) {
  271. // Don't count it as a visible item
  272. $nb_items--;
  273. $total_children --;
  274. }
  275. if($item['verb'] === ACTIVITY_LIKE || $item['verb'] === ACTIVITY_DISLIKE) {
  276. $nb_items --;
  277. $total_children --;
  278. }
  279. }
  280. foreach($items as $item) {
  281. // prevent private email reply to public conversation from leaking.
  282. if($item['network'] === NETWORK_MAIL && local_user() != $item['uid']) {
  283. continue;
  284. }
  285. if($item['verb'] === ACTIVITY_LIKE || $item['verb'] === ACTIVITY_DISLIKE) {
  286. continue;
  287. }
  288. $items_seen++;
  289. $comment = '';
  290. $template = $wall_template;
  291. $commentww = '';
  292. $sparkle = '';
  293. $owner_url = $owner_photo = $owner_name = '';
  294. $buttons = '';
  295. $dropping = false;
  296. $star = false;
  297. $isstarred = "unstarred";
  298. $photo = $item['photo'];
  299. $thumb = $item['thumb'];
  300. $indent = '';
  301. $osparkle = '';
  302. $lastcollapsed = false;
  303. $firstcollapsed = false;
  304. $total_children += count_descendants($item);
  305. $toplevelpost = (($item['id'] == $item['parent']) ? true : false);
  306. $item_writeable = (($item['writable'] || $item['self']) ? true : false);
  307. $show_comment_box = ((($page_writeable) && ($item_writeable)) ? true : false);
  308. $lock = ((($item['private'] == 1) || (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
  309. || strlen($item['deny_cid']) || strlen($item['deny_gid']))))
  310. ? t('Private Message')
  311. : false);
  312. $redirect_url = $a->get_baseurl($ssl_state) . '/redir/' . $item['cid'] ;
  313. $shareable = ((($profile_owner == local_user()) && ($item['private'] != 1)) ? true : false);
  314. if(local_user() && link_compare($a->contact['url'],$item['author-link']))
  315. $edpost = array($a->get_baseurl($ssl_state)."/editpost/".$item['id'], t("Edit"));
  316. else
  317. $edpost = false;
  318. if((intval($item['contact-id']) && $item['contact-id'] == remote_user()) || ($item['uid'] == local_user()))
  319. $dropping = true;
  320. $drop = array(
  321. 'dropping' => $dropping,
  322. 'select' => t('Select'),
  323. 'delete' => t('Delete'),
  324. );
  325. $filer = (($profile_owner == local_user()) ? t("save to folder") : false);
  326. $diff_author = ((link_compare($item['url'],$item['author-link'])) ? false : true);
  327. $profile_name = (((strlen($item['author-name'])) && $diff_author) ? $item['author-name'] : $item['name']);
  328. if($item['author-link'] && (! $item['author-name']))
  329. $profile_name = $item['author-link'];
  330. $sp = false;
  331. $profile_link = best_link_url($item,$sp);
  332. if($profile_link === 'mailbox')
  333. $profile_link = '';
  334. if($sp)
  335. $sparkle = ' sparkle';
  336. else
  337. $profile_link = zrl($profile_link);
  338. $normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']);
  339. if(($normalised != 'mailbox') && (x($a->contacts,$normalised)))
  340. $profile_avatar = $a->contacts[$normalised]['thumb'];
  341. else
  342. $profile_avatar = (((strlen($item['author-avatar'])) && $diff_author) ? $item['author-avatar'] : $a->get_cached_avatar_image($thumb));
  343. $locate = array('location' => $item['location'], 'coord' => $item['coord'], 'html' => '');
  344. call_hooks('render_location',$locate);
  345. $location = ((strlen($locate['html'])) ? $locate['html'] : render_location_google($locate));
  346. $tags=array();
  347. foreach(explode(',',$item['tag']) as $tag){
  348. $tag = trim($tag);
  349. if ($tag!="") $tags[] = bbcode($tag);
  350. }
  351. $like = ((x($alike,$item['uri'])) ? format_like($alike[$item['uri']],$alike[$item['uri'] . '-l'],'like',$item['uri']) : '');
  352. $dislike = ((x($dlike,$item['uri'])) ? format_like($dlike[$item['uri']],$dlike[$item['uri'] . '-l'],'dislike',$item['uri']) : '');
  353. if($toplevelpost) {
  354. if((! $item['self']) && ($mode !== 'profile')) {
  355. if($item['wall']) {
  356. // On the network page, I am the owner. On the display page it will be the profile owner.
  357. // This will have been stored in $a->page_contact by our calling page.
  358. // Put this person as the wall owner of the wall-to-wall notice.
  359. $owner_url = zrl($a->page_contact['url']);
  360. $owner_photo = $a->page_contact['thumb'];
  361. $owner_name = $a->page_contact['name'];
  362. $template = $wallwall_template;
  363. $commentww = 'ww';
  364. }
  365. else if($item['owner-link']) {
  366. $owner_linkmatch = (($item['owner-link']) && link_compare($item['owner-link'],$item['author-link']));
  367. $alias_linkmatch = (($item['alias']) && link_compare($item['alias'],$item['author-link']));
  368. $owner_namematch = (($item['owner-name']) && $item['owner-name'] == $item['author-name']);
  369. if((! $owner_linkmatch) && (! $alias_linkmatch) && (! $owner_namematch)) {
  370. // The author url doesn't match the owner (typically the contact)
  371. // and also doesn't match the contact alias.
  372. // The name match is a hack to catch several weird cases where URLs are
  373. // all over the park. It can be tricked, but this prevents you from
  374. // seeing "Bob Smith to Bob Smith via Wall-to-wall" and you know darn
  375. // well that it's the same Bob Smith.
  376. // But it could be somebody else with the same name. It just isn't highly likely.
  377. $owner_url = $item['owner-link'];
  378. $owner_photo = $item['owner-avatar'];
  379. $owner_name = $item['owner-name'];
  380. $template = $wallwall_template;
  381. $commentww = 'ww';
  382. // If it is our contact, use a friendly redirect link
  383. if((link_compare($item['owner-link'],$item['url']))
  384. && ($item['network'] === NETWORK_DFRN)) {
  385. $owner_url = $redirect_url;
  386. $osparkle = ' sparkle';
  387. }
  388. else
  389. $owner_url = zrl($owner_url);
  390. }
  391. }
  392. }
  393. if($profile_owner == local_user()) {
  394. $isstarred = (($item['starred']) ? "starred" : "unstarred");
  395. $star = array(
  396. 'do' => t("add star"),
  397. 'undo' => t("remove star"),
  398. 'toggle' => t("toggle star status"),
  399. 'classdo' => (($item['starred']) ? "hidden" : ""),
  400. 'classundo' => (($item['starred']) ? "" : "hidden"),
  401. 'starred' => t('starred'),
  402. 'tagger' => t("add tag"),
  403. 'classtagger' => "",
  404. );
  405. }
  406. } else {
  407. $indent = 'comment';
  408. // Collapse comments
  409. if(($nb_items > 2) || ($thread_level > 2)) {
  410. if($items_seen == 1) {
  411. $firstcollapsed = true;
  412. }
  413. if($thread_level > 2) {
  414. if($items_seen == $nb_items)
  415. $lastcollapsed = true;
  416. }
  417. else if($items_seen == ($nb_items - 2)) {
  418. $lastcollapsed = true;
  419. }
  420. }
  421. }
  422. if(intval(get_config('system','thread_allow')) && $a->theme_thread_allow) {
  423. $comments_threaded = true;
  424. }
  425. else {
  426. $comments_threaded = false;
  427. }
  428. if($page_writeable) {
  429. $buttons = array(
  430. 'like' => array( t("I like this \x28toggle\x29"), t("like")),
  431. 'dislike' => array( t("I don't like this \x28toggle\x29"), t("dislike")),
  432. );
  433. if ($shareable) $buttons['share'] = array( t('Share this'), t('share'));
  434. if($show_comment_box) {
  435. $qc = $qcomment = null;
  436. if(in_array('qcomment',$a->plugins)) {
  437. $qc = ((local_user()) ? get_pconfig(local_user(),'qcomment','words') : null);
  438. $qcomment = (($qc) ? explode("\n",$qc) : null);
  439. }
  440. $comment = replace_macros($cmnt_tpl,array(
  441. '$return_path' => '',
  442. '$threaded' => $comments_threaded,
  443. '$jsreload' => (($mode === 'display') ? $_SESSION['return_url'] : ''),
  444. '$type' => (($mode === 'profile') ? 'wall-comment' : 'net-comment'),
  445. '$id' => $item['item_id'],
  446. '$parent' => $item['item_id'],
  447. '$qcomment' => $qcomment,
  448. '$profile_uid' => $profile_owner,
  449. '$mylink' => $a->contact['url'],
  450. '$mytitle' => t('This is you'),
  451. '$myphoto' => $a->contact['thumb'],
  452. '$comment' => t('Comment'),
  453. '$submit' => t('Submit'),
  454. '$edbold' => t('Bold'),
  455. '$editalic' => t('Italic'),
  456. '$eduline' => t('Underline'),
  457. '$edquote' => t('Quote'),
  458. '$edcode' => t('Code'),
  459. '$edimg' => t('Image'),
  460. '$edurl' => t('Link'),
  461. '$edvideo' => t('Video'),
  462. '$preview' => t('Preview'),
  463. '$indent' => $indent,
  464. '$sourceapp' => t($a->sourcename),
  465. '$ww' => (($mode === 'network') ? $commentww : '')
  466. ));
  467. }
  468. }
  469. if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
  470. $indent .= ' shiny';
  471. localize_item($item);
  472. $body = prepare_body($item,true);
  473. $tmp_item = array(
  474. // collapse comments in template. I don't like this much...
  475. 'comment_firstcollapsed' => $firstcollapsed,
  476. 'comment_lastcollapsed' => $lastcollapsed,
  477. // template to use to render item (wall, walltowall, search)
  478. 'template' => $template,
  479. 'type' => implode("",array_slice(explode("/",$item['verb']),-1)),
  480. 'tags' => $tags,
  481. 'body' => template_escape($body),
  482. 'text' => strip_tags(template_escape($body)),
  483. 'id' => $item['item_id'],
  484. 'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])),
  485. 'olinktitle' => sprintf( t('View %s\'s profile @ %s'), $owner_name, ((strlen($item['owner-link'])) ? $item['owner-link'] : $item['url'])),
  486. 'to' => t('to'),
  487. 'wall' => t('Wall-to-Wall'),
  488. 'vwall' => t('via Wall-To-Wall:'),
  489. 'profile_url' => $profile_link,
  490. 'item_photo_menu' => item_photo_menu($item),
  491. 'name' => template_escape($profile_name),
  492. 'thumb' => $profile_avatar,
  493. 'osparkle' => $osparkle,
  494. 'sparkle' => $sparkle,
  495. 'title' => template_escape($item['title']),
  496. 'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'),
  497. 'ago' => (($item['app']) ? sprintf( t('%s from %s'),relative_date($item['created']),$item['app']) : relative_date($item['created'])),
  498. 'lock' => $lock,
  499. 'location' => template_escape($location),
  500. 'indent' => $indent,
  501. 'owner_url' => $owner_url,
  502. 'owner_photo' => $owner_photo,
  503. 'owner_name' => template_escape($owner_name),
  504. 'plink' => get_plink($item),
  505. 'edpost' => $edpost,
  506. 'isstarred' => $isstarred,
  507. 'star' => $star,
  508. 'filer' => $filer,
  509. 'drop' => $drop,
  510. 'vote' => $buttons,
  511. 'like' => $like,
  512. 'dislike' => $dislike,
  513. 'comment' => $comment,
  514. 'previewing' => $previewing,
  515. 'wait' => t('Please wait'),
  516. 'thread_level' => $thread_level,
  517. );
  518. $arr = array('item' => $item, 'output' => $tmp_item);
  519. call_hooks('display_item', $arr);
  520. $item_result = $arr['output'];
  521. if($firstcollapsed) {
  522. $item_result['num_comments'] = sprintf( tt('%d comment','%d comments',$total_children),$total_children );
  523. $item_result['hide_text'] = t('show more');
  524. }
  525. $item_result['children'] = array();
  526. if(count($item['children'])) {
  527. $item_result['children'] = prepare_threads_body($a, $item['children'], $cmnt_tpl, $page_writeable, $mode, $profile_owner, $alike, $dlike, ($thread_level + 1));
  528. }
  529. $item_result['private'] = $item['private'];
  530. $item_result['toplevel'] = ($toplevelpost ? 'toplevel_item' : '');
  531. /*
  532. * I don't like this very much...
  533. */
  534. if(get_config('system','thread_allow') && $a->theme_thread_allow) {
  535. $item_result['flatten'] = false;
  536. $item_result['threaded'] = true;
  537. }
  538. else {
  539. $item_result['flatten'] = true;
  540. $item_result['threaded'] = false;
  541. if(!$toplevelpost) {
  542. $item_result['comment'] = false;
  543. }
  544. }
  545. $result[] = $item_result;
  546. }
  547. return $result;
  548. }
  549. /**
  550. * "Render" a conversation or list of items for HTML display.
  551. * There are two major forms of display:
  552. * - Sequential or unthreaded ("New Item View" or search results)
  553. * - conversation view
  554. * The $mode parameter decides between the various renderings and also
  555. * figures out how to determine page owner and other contextual items
  556. * that are based on unique features of the calling module.
  557. *
  558. */
  559. if(!function_exists('conversation')) {
  560. function conversation(&$a, $items, $mode, $update, $preview = false) {
  561. require_once('bbcode.php');
  562. $ssl_state = ((local_user()) ? true : false);
  563. $profile_owner = 0;
  564. $page_writeable = false;
  565. $previewing = (($preview) ? ' preview ' : '');
  566. if($mode === 'network') {
  567. $profile_owner = local_user();
  568. $page_writeable = true;
  569. }
  570. if($mode === 'profile') {
  571. $profile_owner = $a->profile['profile_uid'];
  572. $page_writeable = can_write_wall($a,$profile_owner);
  573. }
  574. if($mode === 'notes') {
  575. $profile_owner = local_user();
  576. $page_writeable = true;
  577. }
  578. if($mode === 'display') {
  579. $profile_owner = $a->profile['uid'];
  580. $page_writeable = can_write_wall($a,$profile_owner);
  581. }
  582. if($mode === 'community') {
  583. $profile_owner = 0;
  584. $page_writeable = false;
  585. }
  586. $page_dropping = ((local_user() && local_user() == $profile_owner) ? true : false);
  587. if($update)
  588. $return_url = $_SESSION['return_url'];
  589. else
  590. $return_url = $_SESSION['return_url'] = $a->query_string;
  591. load_contact_links(local_user());
  592. $cb = array('items' => $items, 'mode' => $mode, 'update' => $update, 'preview' => $preview);
  593. call_hooks('conversation_start',$cb);
  594. $items = $cb['items'];
  595. $cmnt_tpl = get_markup_template('comment_item.tpl');
  596. $tpl = 'wall_item.tpl';
  597. $wallwall = 'wallwall_item.tpl';
  598. $hide_comments_tpl = get_markup_template('hide_comments.tpl');
  599. $alike = array();
  600. $dlike = array();
  601. // array with html for each thread (parent+comments)
  602. $threads = array();
  603. $threadsid = -1;
  604. $page_template = get_markup_template("conversation.tpl");
  605. if($items && count($items)) {
  606. if($mode === 'network-new' || $mode === 'search' || $mode === 'community') {
  607. // "New Item View" on network page or search page results
  608. // - just loop through the items and format them minimally for display
  609. //$tpl = get_markup_template('search_item.tpl');
  610. $tpl = 'search_item.tpl';
  611. foreach($items as $item) {
  612. $threadsid++;
  613. $comment = '';
  614. $owner_url = '';
  615. $owner_photo = '';
  616. $owner_name = '';
  617. $sparkle = '';
  618. if($mode === 'search' || $mode === 'community') {
  619. if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE)))
  620. && ($item['id'] != $item['parent']))
  621. continue;
  622. $nickname = $item['nickname'];
  623. }
  624. else
  625. $nickname = $a->user['nickname'];
  626. // prevent private email from leaking.
  627. if($item['network'] === NETWORK_MAIL && local_user() != $item['uid'])
  628. continue;
  629. $profile_name = ((strlen($item['author-name'])) ? $item['author-name'] : $item['name']);
  630. if($item['author-link'] && (! $item['author-name']))
  631. $profile_name = $item['author-link'];
  632. $sp = false;
  633. $profile_link = best_link_url($item,$sp);
  634. if($profile_link === 'mailbox')
  635. $profile_link = '';
  636. if($sp)
  637. $sparkle = ' sparkle';
  638. else
  639. $profile_link = zrl($profile_link);
  640. $normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']);
  641. if(($normalised != 'mailbox') && (x($a->contacts[$normalised])))
  642. $profile_avatar = $a->contacts[$normalised]['thumb'];
  643. else
  644. $profile_avatar = ((strlen($item['author-avatar'])) ? $a->get_cached_avatar_image($item['author-avatar']) : $item['thumb']);
  645. $locate = array('location' => $item['location'], 'coord' => $item['coord'], 'html' => '');
  646. call_hooks('render_location',$locate);
  647. $location = ((strlen($locate['html'])) ? $locate['html'] : render_location_google($locate));
  648. localize_item($item);
  649. if($mode === 'network-new')
  650. $dropping = true;
  651. else
  652. $dropping = false;
  653. $drop = array(
  654. 'dropping' => $dropping,
  655. 'select' => t('Select'),
  656. 'delete' => t('Delete'),
  657. );
  658. $star = false;
  659. $isstarred = "unstarred";
  660. $lock = false;
  661. $likebuttons = false;
  662. $shareable = false;
  663. $body = prepare_body($item,true);
  664. //$tmp_item = replace_macros($tpl,array(
  665. $tmp_item = array(
  666. 'template' => $tpl,
  667. 'id' => (($preview) ? 'P0' : $item['item_id']),
  668. 'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])),
  669. 'profile_url' => $profile_link,
  670. 'item_photo_menu' => item_photo_menu($item),
  671. 'name' => template_escape($profile_name),
  672. 'sparkle' => $sparkle,
  673. 'lock' => $lock,
  674. 'thumb' => $profile_avatar,
  675. 'title' => template_escape($item['title']),
  676. 'body' => template_escape($body),
  677. 'text' => strip_tags(template_escape($body)),
  678. 'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'),
  679. 'ago' => (($item['app']) ? sprintf( t('%s from %s'),relative_date($item['created']),$item['app']) : relative_date($item['created'])),
  680. 'location' => template_escape($location),
  681. 'indent' => '',
  682. 'owner_name' => template_escape($owner_name),
  683. 'owner_url' => $owner_url,
  684. 'owner_photo' => $owner_photo,
  685. 'plink' => get_plink($item),
  686. 'edpost' => false,
  687. 'isstarred' => $isstarred,
  688. 'star' => $star,
  689. 'drop' => $drop,
  690. 'vote' => $likebuttons,
  691. 'like' => '',
  692. 'dislike' => '',
  693. 'comment' => '',
  694. 'conv' => (($preview) ? '' : array('href'=> $a->get_baseurl($ssl_state) . '/display/' . $nickname . '/' . $item['id'], 'title'=> t('View in context'))),
  695. 'previewing' => $previewing,
  696. 'wait' => t('Please wait'),
  697. 'thread_level' => 1,
  698. );
  699. $arr = array('item' => $item, 'output' => $tmp_item);
  700. call_hooks('display_item', $arr);
  701. $threads[$threadsid]['id'] = $item['item_id'];
  702. $threads[$threadsid]['items'] = array($arr['output']);
  703. }
  704. }
  705. else
  706. {
  707. // Normal View
  708. $page_template = get_markup_template("threaded_conversation.tpl");
  709. // get all the topmost parents
  710. // this shouldn't be needed, as we should have only them in ou array
  711. // But for now, this array respects the old style, just in case
  712. $threads = array();
  713. foreach($items as $item) {
  714. like_puller($a,$item,$alike,'like');
  715. like_puller($a,$item,$dlike,'dislike');
  716. if($item['id'] == $item['parent']) {
  717. $threads[] = $item;
  718. }
  719. }
  720. $threads = prepare_threads_body($a, $threads, $cmnt_tpl, $page_writeable, $mode, $profile_owner, $alike, $dlike);
  721. }
  722. }
  723. $o = replace_macros($page_template, array(
  724. '$baseurl' => $a->get_baseurl($ssl_state),
  725. '$mode' => $mode,
  726. '$user' => $a->user,
  727. '$threads' => $threads,
  728. '$dropping' => ($page_dropping?t('Delete Selected Items'):False),
  729. ));
  730. return $o;
  731. }}
  732. function best_link_url($item,&$sparkle,$ssl_state = false) {
  733. $a = get_app();
  734. $best_url = '';
  735. $sparkle = false;
  736. $clean_url = normalise_link($item['author-link']);
  737. if((local_user()) && (local_user() == $item['uid'])) {
  738. if(isset($a->contacts) && x($a->contacts,$clean_url)) {
  739. if($a->contacts[$clean_url]['network'] === NETWORK_DFRN) {
  740. $best_url = $a->get_baseurl($ssl_state) . '/redir/' . $a->contacts[$clean_url]['id'];
  741. $sparkle = true;
  742. }
  743. else
  744. $best_url = $a->contacts[$clean_url]['url'];
  745. }
  746. }
  747. if(! $best_url) {
  748. if(strlen($item['author-link']))
  749. $best_url = $item['author-link'];
  750. else
  751. $best_url = $item['url'];
  752. }
  753. return $best_url;
  754. }
  755. if(! function_exists('item_photo_menu')){
  756. function item_photo_menu($item){
  757. $a = get_app();
  758. $ssl_state = false;
  759. if(local_user()) {
  760. $ssl_state = true;
  761. if(! count($a->contacts))
  762. load_contact_links(local_user());
  763. }
  764. $poke_link="";
  765. $contact_url="";
  766. $pm_url="";
  767. $status_link="";
  768. $photos_link="";
  769. $posts_link="";
  770. $sparkle = false;
  771. $profile_link = best_link_url($item,$sparkle,$ssl_state);
  772. if($profile_link === 'mailbox')
  773. $profile_link = '';
  774. if($sparkle) {
  775. $cid = intval(basename($profile_link));
  776. $status_link = $profile_link . "?url=status";
  777. $photos_link = $profile_link . "?url=photos";
  778. $profile_link = $profile_link . "?url=profile";
  779. $pm_url = $a->get_baseurl($ssl_state) . '/message/new/' . $cid;
  780. $zurl = '';
  781. }
  782. else {
  783. $profile_link = zrl($profile_link);
  784. if(local_user() && local_user() == $item['uid'] && link_compare($item['url'],$item['author-link'])) {
  785. $cid = $item['contact-id'];
  786. }
  787. else {
  788. $cid = 0;
  789. }
  790. }
  791. if(($cid) && (! $item['self'])) {
  792. $poke_link = $a->get_baseurl($ssl_state) . '/poke/?f=&c=' . $cid;
  793. $contact_url = $a->get_baseurl($ssl_state) . '/contacts/' . $cid;
  794. $posts_link = $a->get_baseurl($ssl_state) . '/network/?cid=' . $cid;
  795. $clean_url = normalise_link($item['author-link']);
  796. if((local_user()) && (local_user() == $item['uid'])) {
  797. if(isset($a->contacts) && x($a->contacts,$clean_url)) {
  798. if($a->contacts[$clean_url]['network'] === NETWORK_DIASPORA) {
  799. $pm_url = $a->get_baseurl($ssl_state) . '/message/new/' . $cid;
  800. }
  801. }
  802. }
  803. }
  804. $menu = Array(
  805. t("View Status") => $status_link,
  806. t("View Profile") => $profile_link,
  807. t("View Photos") => $photos_link,
  808. t("Network Posts") => $posts_link,
  809. t("Edit Contact") => $contact_url,
  810. t("Send PM") => $pm_url,
  811. t("Poke") => $poke_link
  812. );
  813. $args = array('item' => $item, 'menu' => $menu);
  814. call_hooks('item_photo_menu', $args);
  815. $menu = $args['menu'];
  816. $o = "";
  817. foreach($menu as $k=>$v){
  818. if ($v!="") $o .= "<li><a href=\"$v\">$k</a></li>\n";
  819. }
  820. return $o;
  821. }}
  822. if(! function_exists('like_puller')) {
  823. function like_puller($a,$item,&$arr,$mode) {
  824. $url = '';
  825. $sparkle = '';
  826. $verb = (($mode === 'like') ? ACTIVITY_LIKE : ACTIVITY_DISLIKE);
  827. if((activity_match($item['verb'],$verb)) && ($item['id'] != $item['parent'])) {
  828. $url = $item['author-link'];
  829. if((local_user()) && (local_user() == $item['uid']) && ($item['network'] === 'dfrn') && (! $item['self']) && (link_compare($item['author-link'],$item['url']))) {
  830. $url = $a->get_baseurl(true) . '/redir/' . $item['contact-id'];
  831. $sparkle = ' class="sparkle" ';
  832. }
  833. else
  834. $url = zrl($url);
  835. if(! $item['thr-parent'])
  836. $item['thr-parent'] = $item['parent-uri'];
  837. if(! ((isset($arr[$item['thr-parent'] . '-l'])) && (is_array($arr[$item['thr-parent'] . '-l']))))
  838. $arr[$item['thr-parent'] . '-l'] = array();
  839. if(! isset($arr[$item['thr-parent']]))
  840. $arr[$item['thr-parent']] = 1;
  841. else
  842. $arr[$item['thr-parent']] ++;
  843. $arr[$item['thr-parent'] . '-l'][] = '<a href="'. $url . '"'. $sparkle .'>' . $item['author-name'] . '</a>';
  844. }
  845. return;
  846. }}
  847. // Format the like/dislike text for a profile item
  848. // $cnt = number of people who like/dislike the item
  849. // $arr = array of pre-linked names of likers/dislikers
  850. // $type = one of 'like, 'dislike'
  851. // $id = item id
  852. // returns formatted text
  853. if(! function_exists('format_like')) {
  854. function format_like($cnt,$arr,$type,$id) {
  855. $o = '';
  856. if($cnt == 1)
  857. $o .= (($type === 'like') ? sprintf( t('%s likes this.'), $arr[0]) : sprintf( t('%s doesn\'t like this.'), $arr[0])) . EOL ;
  858. else {
  859. $spanatts = 'class="fakelink" onclick="openClose(\'' . $type . 'list-' . $id . '\');"';
  860. $o .= (($type === 'like') ?
  861. sprintf( t('<span %1$s>%2$d people</span> like this.'), $spanatts, $cnt)
  862. :
  863. sprintf( t('<span %1$s>%2$d people</span> don\'t like this.'), $spanatts, $cnt) );
  864. $o .= EOL ;
  865. $total = count($arr);
  866. if($total >= MAX_LIKERS)
  867. $arr = array_slice($arr, 0, MAX_LIKERS - 1);
  868. if($total < MAX_LIKERS)
  869. $arr[count($arr)-1] = t('and') . ' ' . $arr[count($arr)-1];
  870. $str = implode(', ', $arr);
  871. if($total >= MAX_LIKERS)
  872. $str .= sprintf( t(', and %d other people'), $total - MAX_LIKERS );
  873. $str = (($type === 'like') ? sprintf( t('%s like this.'), $str) : sprintf( t('%s don\'t like this.'), $str));
  874. $o .= "\t" . '<div id="' . $type . 'list-' . $id . '" style="display: none;" >' . $str . '</div>';
  875. }
  876. return $o;
  877. }}
  878. function status_editor($a,$x, $notes_cid = 0, $popup=false) {
  879. $o = '';
  880. $geotag = (($x['allow_location']) ? get_markup_template('jot_geotag.tpl') : '');
  881. $plaintext = false;
  882. if(local_user() && intval(get_pconfig(local_user(),'system','plaintext')))
  883. $plaintext = true;
  884. $tpl = get_markup_template('jot-header.tpl');
  885. $a->page['htmlhead'] .= replace_macros($tpl, array(
  886. '$newpost' => 'true',
  887. '$baseurl' => $a->get_baseurl(true),
  888. '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
  889. '$geotag' => $geotag,
  890. '$nickname' => $x['nickname'],
  891. '$ispublic' => t('Visible to <strong>everybody</strong>'),
  892. '$linkurl' => t('Please enter a link URL:'),
  893. '$vidurl' => t("Please enter a video link/URL:"),
  894. '$audurl' => t("Please enter an audio link/URL:"),
  895. '$term' => t('Tag term:'),
  896. '$fileas' => t('Save to Folder:'),
  897. '$whereareu' => t('Where are you right now?')
  898. ));
  899. $tpl = get_markup_template('jot-end.tpl');
  900. $a->page['end'] .= replace_macros($tpl, array(
  901. '$newpost' => 'true',
  902. '$baseurl' => $a->get_baseurl(true),
  903. '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
  904. '$geotag' => $geotag,
  905. '$nickname' => $x['nickname'],
  906. '$ispublic' => t('Visible to <strong>everybody</strong>'),
  907. '$linkurl' => t('Please enter a link URL:'),
  908. '$vidurl' => t("Please enter a video link/URL:"),
  909. '$audurl' => t("Please enter an audio link/URL:"),
  910. '$term' => t('Tag term:'),
  911. '$fileas' => t('Save to Folder:'),
  912. '$whereareu' => t('Where are you right now?')
  913. ));
  914. $tpl = get_markup_template("jot.tpl");
  915. $jotplugins = '';
  916. $jotnets = '';
  917. $mail_disabled = ((function_exists('imap_open') && (! get_config('system','imap_disabled'))) ? 0 : 1);
  918. $mail_enabled = false;
  919. $pubmail_enabled = false;
  920. if(($x['is_owner']) && (! $mail_disabled)) {
  921. $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1",
  922. intval(local_user())
  923. );
  924. if(count($r)) {
  925. $mail_enabled = true;
  926. if(intval($r[0]['pubmail']))
  927. $pubmail_enabled = true;
  928. }
  929. }
  930. if($mail_enabled) {
  931. $selected = (($pubmail_enabled) ? ' checked="checked" ' : '');
  932. $jotnets .= '<div class="profile-jot-net"><input type="checkbox" name="pubmail_enable"' . $selected . ' value="1" /> ' . t("Post to Email") . '</div>';
  933. }
  934. call_hooks('jot_tool', $jotplugins);
  935. call_hooks('jot_networks', $jotnets);
  936. if($notes_cid)
  937. $jotnets .= '<input type="hidden" name="contact_allow[]" value="' . $notes_cid .'" />';
  938. $tpl = replace_macros($tpl,array('$jotplugins' => $jotplugins));
  939. $o .= replace_macros($tpl,array(
  940. '$return_path' => $a->query_string,
  941. '$action' => $a->get_baseurl(true) . '/item',
  942. '$share' => (x($x,'button') ? $x['button'] : t('Share')),
  943. '$upload' => t('Upload photo'),
  944. '$shortupload' => t('upload photo'),
  945. '$attach' => t('Attach file'),
  946. '$shortattach' => t('attach file'),
  947. '$weblink' => t('Insert web link'),
  948. '$shortweblink' => t('web link'),
  949. '$video' => t('Insert video link'),
  950. '$shortvideo' => t('video link'),
  951. '$audio' => t('Insert audio link'),
  952. '$shortaudio' => t('audio link'),
  953. '$setloc' => t('Set your location'),
  954. '$shortsetloc' => t('set location'),
  955. '$noloc' => t('Clear browser location'),
  956. '$shortnoloc' => t('clear location'),
  957. '$title' => "",
  958. '$placeholdertitle' => t('Set title'),
  959. '$category' => "",
  960. '$placeholdercategory' => t('Categories (comma-separated list)'),
  961. '$wait' => t('Please wait'),
  962. '$permset' => t('Permission settings'),
  963. '$shortpermset' => t('permissions'),
  964. '$ptyp' => (($notes_cid) ? 'note' : 'wall'),
  965. '$content' => '',
  966. '$post_id' => '',
  967. '$baseurl' => $a->get_baseurl(true),
  968. '$defloc' => $x['default_location'],
  969. '$visitor' => $x['visitor'],
  970. '$pvisit' => (($notes_cid) ? 'none' : $x['visitor']),
  971. '$emailcc' => t('CC: email addresses'),
  972. '$public' => t('Public post'),
  973. '$jotnets' => $jotnets,
  974. '$emtitle' => t('Example: bob@example.com, mary@example.com'),
  975. '$lockstate' => $x['lockstate'],
  976. '$acl' => $x['acl'],
  977. '$bang' => $x['bang'],
  978. '$profile_uid' => $x['profile_uid'],
  979. '$preview' => t('Preview'),
  980. '$sourceapp' => t($a->sourcename),
  981. ));
  982. if ($popup==true){
  983. $o = '<div id="jot-popup" style="display: none;">'.$o.'</div>';
  984. }
  985. return $o;
  986. }
  987. function get_item_children($arr, $parent) {
  988. $children = array();
  989. foreach($arr as $item) {
  990. if($item['id'] != $item['parent']) {
  991. if(get_config('system','thread_allow')) {
  992. // Fallback to parent-uri if thr-parent is not set
  993. $thr_parent = $item['thr-parent'];
  994. if($thr_parent == '')
  995. $thr_parent = $item['parent-uri'];
  996. if($thr_parent == $parent['uri']) {
  997. $item['children'] = get_item_children($arr, $item);
  998. $children[] = $item;
  999. }
  1000. }
  1001. else if($item['parent'] == $parent['id']) {
  1002. $children[] = $item;
  1003. }
  1004. }
  1005. }
  1006. return $children;
  1007. }
  1008. function sort_item_children($items) {
  1009. $result = $items;
  1010. usort($result,'sort_thr_created_rev');
  1011. foreach($result as $k => $i) {
  1012. if(count($result[$k]['children'])) {
  1013. $result[$k]['children'] = sort_item_children($result[$k]['children']);
  1014. }
  1015. }
  1016. return $result;
  1017. }
  1018. function add_children_to_list($children, &$arr) {
  1019. foreach($children as $y) {
  1020. $arr[] = $y;
  1021. if(count($y['children']))
  1022. add_children_to_list($y['children'], $arr);
  1023. }
  1024. }
  1025. function conv_sort($arr,$order) {
  1026. if((!(is_array($arr) && count($arr))))
  1027. return array();
  1028. $parents = array();
  1029. $children = array();
  1030. foreach($arr as $x)
  1031. if($x['id'] == $x['parent'])
  1032. $parents[] = $x;
  1033. if(stristr($order,'created'))
  1034. usort($parents,'sort_thr_created');
  1035. elseif(stristr($order,'commented'))
  1036. usort($parents,'sort_thr_commented');
  1037. if(count($parents))
  1038. foreach($parents as $i=>$_x)
  1039. $parents[$i]['children'] = get_item_children($arr, $_x);
  1040. /*foreach($arr as $x) {
  1041. if($x['id'] != $x['parent']) {
  1042. $p = find_thread_parent_index($parents,$x);
  1043. if($p !== false)
  1044. $parents[$p]['children'][] = $x;
  1045. }
  1046. }*/
  1047. if(count($parents)) {
  1048. foreach($parents as $k => $v) {
  1049. if(count($parents[$k]['children'])) {
  1050. $parents[$k]['children'] = sort_item_children($parents[$k]['children']);
  1051. /*$y = $parents[$k]['children'];
  1052. usort($y,'sort_thr_created_rev');
  1053. $parents[$k]['children'] = $y;*/
  1054. }
  1055. }
  1056. }
  1057. $ret = array();
  1058. if(count($parents)) {
  1059. foreach($parents as $x) {
  1060. $ret[] = $x;
  1061. if(count($x['children']))
  1062. add_children_to_list($x['children'], $ret);
  1063. /*foreach($x['children'] as $y)
  1064. $ret[] = $y;*/
  1065. }
  1066. }
  1067. return $ret;
  1068. }
  1069. function sort_thr_created($a,$b) {
  1070. return strcmp($b['created'],$a['created']);
  1071. }
  1072. function sort_thr_created_rev($a,$b) {
  1073. return strcmp($a['created'],$b['created']);
  1074. }
  1075. function sort_thr_commented($a,$b) {
  1076. return strcmp($b['commented'],$a['commented']);
  1077. }
  1078. function find_thread_parent_index($arr,$x) {
  1079. foreach($arr as $k => $v)
  1080. if($v['id'] == $x['parent'])
  1081. return $k;
  1082. return false;
  1083. }
  1084. function render_location_google($item) {
  1085. $location = (($item['location']) ? '<a target="map" title="' . $item['location'] . '" href="http://maps.google.com/?q=' . urlencode($item['location']) . '">' . $item['location'] . '</a>' : '');
  1086. $coord = (($item['coord']) ? '<a target="map" title="' . $item['coord'] . '" href="http://maps.google.com/?q=' . urlencode($item['coord']) . '">' . $item['coord'] . '</a>' : '');
  1087. if($coord) {
  1088. if($location)
  1089. $location .= '<br /><span class="smalltext">(' . $coord . ')</span>';
  1090. else
  1091. $location = '<span class="smalltext">' . $coord . '</span>';
  1092. }
  1093. return $location;
  1094. }