X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Fconversation.php;h=5d64bcef763c4bd06e9f3b158b50dc7e81814711;hb=008c97c570ea62749a3f486b42c424365863d627;hp=e58df19f16cc03908d0c71174fc569750b4530ff;hpb=181947f774c878f806a72de391fbab7fb5b273f5;p=friendica.git diff --git a/include/conversation.php b/include/conversation.php index e58df19f16..5d64bcef76 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1,16 +1,20 @@ $new_body, 'images' => $saved_image); -}} +} -if (! function_exists('item_redir_and_replace_images')) { function item_redir_and_replace_images($body, $images, $cid) { $origbody = $body; @@ -65,7 +68,7 @@ function item_redir_and_replace_images($body, $images, $cid) { while ($pos !== false && $cnt < 1000) { $search = '/\[url\=(.*?)\]\[!#saved_image([0-9]*)#!\]\[\/url\]' . '/is'; - $replace = '[url=' . z_path() . '/redir/' . $cid + $replace = '[url=' . System::baseUrl() . '/redir/' . $cid . '?f=1&url=' . '$1' . '][!#saved_image' . '$2' .'#!][/url]'; $newbody .= substr($origbody, 0, $pos['start']['open']); @@ -94,7 +97,7 @@ function item_redir_and_replace_images($body, $images, $cid) { $cnt++; } return $newbody; -}} +} /** * Render actions localized @@ -119,7 +122,7 @@ function localize_item(&$item) { WHERE `item`.`contact-id`=`contact`.`id` AND `item`.`uri`='%s'", dbesc($item['parent-uri'])); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } $obj = $r[0]; @@ -248,20 +251,6 @@ function localize_item(&$item) { $item['body'] = sprintf($txt, $A, $B). "\n\n\n" . $Bphoto; } - if (stristr($item['verb'], ACTIVITY_MOOD)) { - $verb = urldecode(substr($item['verb'], strpos($item['verb'], '#') + 1)); - if (! $verb) { - return; - } - - $Aname = $item['author-name']; - $Alink = $item['author-link']; - $A = '[url=' . zrl($Alink) . ']' . $Aname . '[/url]'; - - $txt = t('%1$s is currently %2$s'); - - $item['body'] = sprintf($txt, $A, t($verb)); - } if (activity_match($item['verb'], ACTIVITY_TAG)) { /// @TODO may hurt performance "joining" two tables + asterisk @@ -270,7 +259,7 @@ function localize_item(&$item) { AND `item`.`uri`='%s'", dbesc($item['parent-uri'])); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } @@ -326,7 +315,7 @@ function localize_item(&$item) { intval($item['uid']) ); - if (dbm::is_result($r) && $r[0]['plink']) { + if (DBM::is_result($r) && $r[0]['plink']) { $target = $r[0]; $Bname = $target['author-name']; $Blink = $target['author-link']; @@ -358,7 +347,7 @@ function localize_item(&$item) { $x = stristr($item['plink'],'/display/'); if ($x) { $sparkle = false; - $y = best_link_url($item, $sparkle, true); + $y = best_link_url($item, $sparkle); if (strstr($y, '/redir/')) { $item['plink'] = $y . '?f=&url=' . $item['plink']; @@ -424,7 +413,6 @@ function item_fieldlists() { These Fields are not added below (yet). They are here to for bug search. `item`.`type`, `item`.`extid`, -`item`.`received`, `item`.`changed`, `item`.`moderated`, `item`.`target-type`, @@ -451,7 +439,7 @@ These Fields are not added below (yet). They are here to for bug search. `item`.`owner-id`, `item`.`owner-link`, `item`.`owner-name`, `item`.`owner-avatar`, `item`.`contact-id`, `item`.`uid`, `item`.`id`, `item`.`parent`, `item`.`uri`, `item`.`thr-parent`, `item`.`parent-uri`, - `item`.`commented`, `item`.`created`, `item`.`edited`, + `item`.`commented`, `item`.`created`, `item`.`edited`, `item`.`received`, `item`.`verb`, `item`.`object-type`, `item`.`postopts`, `item`.`plink`, `item`.`guid`, `item`.`wall`, `item`.`private`, `item`.`starred`, `item`.`title`, `item`.`body`, `item`.`file`, `item`.`event-id`, @@ -463,7 +451,14 @@ These Fields are not added below (yet). They are here to for bug search. `author`.`thumb` AS `author-thumb`, `owner`.`thumb` AS `owner-thumb`, `contact`.`network`, `contact`.`url`, `contact`.`name`, `contact`.`writable`, - `contact`.`self`, `contact`.`id` AS `cid`, `contact`.`alias`"; + `contact`.`self`, `contact`.`id` AS `cid`, `contact`.`alias`, + + `event`.`created` AS `event-created`, `event`.`edited` AS `event-edited`, + `event`.`start` AS `event-start`,`event`.`finish` AS `event-finish`, + `event`.`summary` AS `event-summary`,`event`.`desc` AS `event-desc`, + `event`.`location` AS `event-location`, `event`.`type` AS `event-type`, + `event`.`nofinish` AS `event-nofinish`,`event`.`adjust` AS `event-adjust`, + `event`.`ignore` AS `event-ignore`, `event`.`id` AS `event-id`"; } /** @@ -473,7 +468,8 @@ function item_joins() { return "STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND (NOT `contact`.`blocked` OR `contact`.`pending`) LEFT JOIN `contact` AS `author` ON `author`.`id`=`item`.`author-id` - LEFT JOIN `contact` AS `owner` ON `owner`.`id`=`item`.`owner-id`"; + LEFT JOIN `contact` AS `owner` ON `owner`.`id`=`item`.`owner-id` + LEFT JOIN `event` ON `event-id` = `event`.`id`"; } /** @@ -483,7 +479,6 @@ function item_condition() { return "`item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`"; } -if (!function_exists('conversation')) { /** * "Render" a conversation or list of items for HTML display. * There are two major forms of display: @@ -497,7 +492,6 @@ if (!function_exists('conversation')) { function conversation(App $a, $items, $mode, $update, $preview = false) { require_once 'include/bbcode.php'; - require_once 'include/Contact.php'; require_once 'mod/proxy.php'; $ssl_state = ((local_user()) ? true : false); @@ -509,7 +503,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { $arr_blocked = null; if (local_user()) { - $str_blocked = get_pconfig(local_user(), 'system', 'blocked'); + $str_blocked = PConfig::get(local_user(), 'system', 'blocked'); if ($str_blocked) { $arr_blocked = explode(',', $str_blocked); for ($x = 0; $x < count($arr_blocked); $x ++) { @@ -681,15 +675,19 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { $hashtags = array(); $mentions = array(); - $taglist = q("SELECT `type`, `term`, `url` FROM `term` WHERE `otype` = %d AND `oid` = %d AND `type` IN (%d, %d) ORDER BY `tid`", - intval(TERM_OBJ_POST), intval($item['id']), intval(TERM_HASHTAG), intval(TERM_MENTION)); + $searchpath = System::baseUrl()."/search?tag="; - foreach ($taglist as $tag) { + $taglist = dba::select('term', array('type', 'term', 'url'), + array("`otype` = ? AND `oid` = ? AND `type` IN (?, ?)", TERM_OBJ_POST, $item['id'], TERM_HASHTAG, TERM_MENTION), + array('order' => array('tid'))); + while ($tag = dba::fetch($taglist)) { if ($tag["url"] == "") { $tag["url"] = $searchpath . strtolower($tag["term"]); } + $tag["url"] = best_link_url($item, $sp, $tag["url"]); + if ($tag["type"] == TERM_HASHTAG) { $hashtags[] = "#" . $tag["term"] . ""; $prefix = "#"; @@ -699,9 +697,10 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { } $tags[] = $prefix."" . $tag["term"] . ""; } + dba::close($taglist); $sp = false; - $profile_link = best_link_url($item,$sp); + $profile_link = best_link_url($item, $sp); if ($profile_link === 'mailbox') { $profile_link = ''; } @@ -713,7 +712,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { } if (!x($item, 'author-thumb') || ($item['author-thumb'] == "")) { - $author_contact = get_contact_details_by_url($item['author-link'], $profile_owner); + $author_contact = Contact::getDetailsByURL($item['author-link'], $profile_owner); if ($author_contact["thumb"]) { $item['author-thumb'] = $author_contact["thumb"]; } else { @@ -722,7 +721,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { } if (!isset($item['owner-thumb']) || ($item['owner-thumb'] == "")) { - $owner_contact = get_contact_details_by_url($item['owner-link'], $profile_owner); + $owner_contact = Contact::getDetailsByURL($item['owner-link'], $profile_owner); if ($owner_contact["thumb"]) { $item['owner-thumb'] = $owner_contact["thumb"]; } else { @@ -760,25 +759,14 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { list($categories, $folders) = get_cats_and_terms($item); - if ($a->theme['template_engine'] === 'internal') { - $profile_name_e = template_escape($profile_name); - $item['title_e'] = template_escape($item['title']); - $body_e = template_escape($body); - $tags_e = template_escape($tags); - $hashtags_e = template_escape($hashtags); - $mentions_e = template_escape($mentions); - $location_e = template_escape($location); - $owner_name_e = template_escape($owner_name); - } else { - $profile_name_e = $profile_name; - $item['title_e'] = $item['title']; - $body_e = $body; - $tags_e = $tags; - $hashtags_e = $hashtags; - $mentions_e = $mentions; - $location_e = $location; - $owner_name_e = $owner_name; - } + $profile_name_e = $profile_name; + $item['title_e'] = $item['title']; + $body_e = $body; + $tags_e = $tags; + $hashtags_e = $hashtags; + $mentions_e = $mentions; + $location_e = $location; + $owner_name_e = $owner_name; if ($item['item_network'] == "") { $item['item_network'] = $item['network']; @@ -787,6 +775,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { $tmp_item = array( 'template' => $tpl, 'id' => (($preview) ? 'P0' : $item['item_id']), + 'guid' => (($preview) ? 'Q0' : $item['guid']), 'network' => $item['item_network'], 'network_name' => network_to_name($item['item_network'], $profile_link), 'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])), @@ -795,7 +784,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { 'name' => $profile_name_e, 'sparkle' => $sparkle, 'lock' => $lock, - 'thumb' => App::remove_baseurl(proxy_url($item['author-thumb'], false, PROXY_SIZE_THUMB)), + 'thumb' => System::removedBaseUrl(proxy_url($item['author-thumb'], false, PROXY_SIZE_THUMB)), 'title' => $item['title_e'], 'body' => $body_e, 'tags' => $tags_e, @@ -814,7 +803,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { 'indent' => '', 'owner_name' => $owner_name_e, 'owner_url' => $owner_url, - 'owner_photo' => App::remove_baseurl(proxy_url($item['owner-thumb'], false, PROXY_SIZE_THUMB)), + 'owner_photo' => System::removedBaseUrl(proxy_url($item['owner-thumb'], false, PROXY_SIZE_THUMB)), 'plink' => get_plink($item), 'edpost' => false, 'isstarred' => $isstarred, @@ -843,10 +832,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { // Normal View $page_template = get_markup_template("threaded_conversation.tpl"); - require_once 'object/Conversation.php'; - require_once 'object/Item.php'; - - $conv = new Conversation($mode, $preview); + $conv = new Thread($mode, $preview); /* * get all the topmost parents @@ -886,12 +872,12 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { $item['pagedrop'] = $page_dropping; if ($item['id'] == $item['parent']) { - $item_object = new Item($item); - $conv->add_thread($item_object); + $item_object = new Post($item); + $conv->addParent($item_object); } } - $threads = $conv->get_template_data($conv_responses); + $threads = $conv->getTemplateData($conv_responses); if (!$threads) { logger('[ERROR] conversation : Failed to get template data.', LOGGER_DEBUG); @@ -901,20 +887,20 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { } $o = replace_macros($page_template, array( - '$baseurl' => App::get_baseurl($ssl_state), + '$baseurl' => System::baseUrl($ssl_state), '$return_path' => $a->query_string, '$live_update' => $live_update_div, '$remove' => t('remove'), '$mode' => $mode, '$user' => $a->user, '$threads' => $threads, - '$dropping' => ($page_dropping && feature_enabled(local_user(), 'multi_delete') ? t('Delete Selected Items') : False), + '$dropping' => ($page_dropping && Feature::isEnabled(local_user(), 'multi_delete') ? t('Delete Selected Items') : False), )); return $o; -}} +} -function best_link_url($item, &$sparkle, $ssl_state = false) { +function best_link_url($item, &$sparkle, $url = '') { $best_url = ''; $sparkle = false; @@ -922,15 +908,26 @@ function best_link_url($item, &$sparkle, $ssl_state = false) { $clean_url = normalise_link($item['author-link']); if (local_user()) { - $r = q("SELECT `id` FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `nurl` = '%s' AND NOT `pending` LIMIT 1", - dbesc(NETWORK_DFRN), intval(local_user()), dbesc(normalise_link($clean_url))); - if (dbm::is_result($r)) { - $best_url = 'redir/' . $r[0]['id']; + $r = dba::select('contact', array('id'), + array('network' => NETWORK_DFRN, 'uid' => local_user(), 'nurl' => normalise_link($clean_url), 'pending' => false), + array('limit' => 1)); + if (DBM::is_result($r)) { + $best_url = 'redir/' . $r['id']; $sparkle = true; + if ($url != '') { + $hostname = get_app()->get_hostname(); + if (!strstr($url, $hostname)) { + $best_url .= "?url=".$url; + } else { + $best_url = $url; + } + } } } if (! $best_url) { - if (strlen($item['author-link'])) { + if ($url != '') { + $best_url = $url; + } elseif (strlen($item['author-link'])) { $best_url = $item['author-link']; } else { $best_url = $item['url']; @@ -941,14 +938,7 @@ function best_link_url($item, &$sparkle, $ssl_state = false) { } -if (! function_exists('item_photo_menu')) { function item_photo_menu($item) { - $ssl_state = false; - - if (local_user()) { - $ssl_state = true; - } - $sub_link = ''; $poke_link = ''; $contact_url = ''; @@ -963,7 +953,7 @@ function item_photo_menu($item) { } $sparkle = false; - $profile_link = best_link_url($item, $sparkle, $ssl_state); + $profile_link = best_link_url($item, $sparkle); if ($profile_link === 'mailbox') { $profile_link = ''; } @@ -971,12 +961,11 @@ function item_photo_menu($item) { $cid = 0; $network = ''; $rel = 0; - $r = q("SELECT `id`, `network`, `rel` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' LIMIT 1", - intval(local_user()), dbesc(normalise_link($item['author-link']))); - if (dbm::is_result($r)) { - $cid = $r[0]['id']; - $network = $r[0]['network']; - $rel = $r[0]['rel']; + $r = dba::select('contact', array('id', 'network', 'rel'), array('uid' => local_user(), 'nurl' => normalise_link($item['author-link'])), array('limit' => 1)); + if (DBM::is_result($r)) { + $cid = $r['id']; + $network = $r['network']; + $rel = $r['rel']; } if ($sparkle) { @@ -1037,9 +1026,8 @@ function item_photo_menu($item) { } } return $o; -}} +} -if (! function_exists('builtin_activity_puller')) { /** * @brief Checks item to see if it is one of the builtin activities (like/dislike, event attendance, consensus items, etc.) * Increments the count of each matching activity and adds a link to the author as needed. @@ -1115,9 +1103,8 @@ function builtin_activity_puller($item, &$conv_responses) { return; } } -}} +} -if (! function_exists('format_like')) { /** * Format the vote text for a profile item * @param int $cnt = number of people who vote the item @@ -1208,7 +1195,7 @@ function format_like($cnt, array $arr, $type, $id) { $o .= $expanded; return $o; -}} +} function status_editor(App $a, $x, $notes_cid = 0, $popup = false) { $o = ''; @@ -1218,7 +1205,7 @@ function status_editor(App $a, $x, $notes_cid = 0, $popup = false) { $tpl = get_markup_template('jot-header.tpl'); $a->page['htmlhead'] .= replace_macros($tpl, array( '$newpost' => 'true', - '$baseurl' => App::get_baseurl(true), + '$baseurl' => System::baseUrl(true), '$geotag' => $geotag, '$nickname' => $x['nickname'], '$ispublic' => t('Visible to everybody'), @@ -1234,7 +1221,7 @@ function status_editor(App $a, $x, $notes_cid = 0, $popup = false) { $tpl = get_markup_template('jot-end.tpl'); $a->page['end'] .= replace_macros($tpl, array( '$newpost' => 'true', - '$baseurl' => App::get_baseurl(true), + '$baseurl' => System::baseUrl(true), '$geotag' => $geotag, '$nickname' => $x['nickname'], '$ispublic' => t('Visible to everybody'), @@ -1295,14 +1282,14 @@ function status_editor(App $a, $x, $notes_cid = 0, $popup = false) { '$title' => $x['title'], '$placeholdertitle' => t('Set title'), '$category' => $x['category'], - '$placeholdercategory' => (feature_enabled(local_user(), 'categories') ? t('Categories (comma-separated list)') : ''), + '$placeholdercategory' => (Feature::isEnabled(local_user(), 'categories') ? t('Categories (comma-separated list)') : ''), '$wait' => t('Please wait'), '$permset' => t('Permission settings'), '$shortpermset' => t('permissions'), '$ptyp' => (($notes_cid) ? 'note' : 'wall'), '$content' => $x['content'], '$post_id' => $x['post_id'], - '$baseurl' => App::get_baseurl(true), + '$baseurl' => System::baseUrl(true), '$defloc' => $x['default_location'], '$visitor' => $x['visitor'], '$pvisit' => (($notes_cid) ? 'none' : $x['visitor']), @@ -1311,7 +1298,7 @@ function status_editor(App $a, $x, $notes_cid = 0, $popup = false) { '$lockstate' => $x['lockstate'], '$bang' => $x['bang'], '$profile_uid' => $x['profile_uid'], - '$preview' => ((feature_enabled($x['profile_uid'],'preview')) ? t('Preview') : ''), + '$preview' => ((Feature::isEnabled($x['profile_uid'],'preview')) ? t('Preview') : ''), '$jotplugins' => $jotplugins, '$notes_cid' => $notes_cid, '$sourceapp' => t($a->sourcename), @@ -1340,13 +1327,22 @@ function status_editor(App $a, $x, $notes_cid = 0, $popup = false) { return $o; } - -function get_item_children($arr, $parent) { - $children = array(); - $a = get_app(); - foreach ($arr as $item) { +/** + * Plucks the children of the given parent from a given item list. + * + * @brief Plucks all the children in the given item list of the given parent + * + * @param array $item_list + * @param array $parent + * @param bool $recursive + * @return type + */ +function get_item_children(array &$item_list, array $parent, $recursive = true) +{ + $children = []; + foreach ($item_list as $i => $item) { if ($item['id'] != $item['parent']) { - if (get_config('system', 'thread_allow') && $a->theme_thread_allow) { + if ($recursive) { // Fallback to parent-uri if thr-parent is not set $thr_parent = $item['thr-parent']; if ($thr_parent == '') { @@ -1354,65 +1350,141 @@ function get_item_children($arr, $parent) { } if ($thr_parent == $parent['uri']) { - $item['children'] = get_item_children($arr, $item); + $item['children'] = get_item_children($item_list, $item); $children[] = $item; + unset($item_list[$i]); } } elseif ($item['parent'] == $parent['id']) { $children[] = $item; + unset($item_list[$i]); } } } return $children; } -/// @TODO Add type-hint -function sort_item_children($items) { +/** + * @brief Recursively sorts a tree-like item array + * + * @param array $items + * @return array + */ +function sort_item_children(array $items) +{ $result = $items; usort($result, 'sort_thr_created_rev'); foreach ($result as $k => $i) { - if (count($result[$k]['children'])) { + if (isset($result[$k]['children'])) { $result[$k]['children'] = sort_item_children($result[$k]['children']); } } return $result; } -/// @TODO Add type-hint -function add_children_to_list($children, &$arr) { - foreach ($children as $y) { - $arr[] = $y; - if (count($y['children'])) { - add_children_to_list($y['children'], $arr); +/** + * @brief Recursively add all children items at the top level of a list + * + * @param array $children List of items to append + * @param array $item_list + */ +function add_children_to_list(array $children, array &$item_list) +{ + foreach ($children as $child) { + $item_list[] = $child; + if (isset($child['children'])) { + add_children_to_list($child['children'], $item_list); } } } -/// @TODO Add type-hint -function conv_sort($arr, $order) { - - if ((!(is_array($arr) && count($arr)))) { - return array(); +/** + * This recursive function takes the item tree structure created by conv_sort() and + * flatten the extraneous depth levels when people reply sequentially, removing the + * stairs effect in threaded conversations limiting the available content width. + * + * The basic principle is the following: if a post item has only one reply and is + * the last reply of its parent, then the reply is moved to the parent. + * + * This process is rendered somewhat more complicated because items can be either + * replies or likes, and these don't factor at all in the reply count/last reply. + * + * @brief Selectively flattens a tree-like item structure to prevent threading stairs + * + * @param array $parent A tree-like array of items + * @return array + */ +function smart_flatten_conversation(array $parent) +{ + if (! isset($parent['children']) || count($parent['children']) == 0) { + return $parent; } - $parents = array(); - $children = array(); - $newarr = array(); + // We use a for loop to ensure we process the newly-moved items + for ($i = 0; $i < count($parent['children']); $i++) { + $child = $parent['children'][$i]; - /* - * This is a preparation for having two different items with the same uri in one thread - * This will otherwise lead to an endless loop. - */ - foreach ($arr as $x) { - if (!isset($newarr[$x['uri']])) { - $newarr[$x['uri']] = $x; + if (isset($child['children']) && count($child['children'])) { + // This helps counting only the regular posts + $count_post_closure = function($var) { + return $var['verb'] === ACTIVITY_POST; + }; + + $child_post_count = count(array_filter($child['children'], $count_post_closure)); + + $remaining_post_count = count(array_filter(array_slice($parent['children'], $i), $count_post_closure)); + + // If there's only one child's children post and this is the last child post + if ($child_post_count == 1 && $remaining_post_count == 1) { + + // Searches the post item in the children + $j = 0; + while($child['children'][$j]['verb'] !== ACTIVITY_POST && $j < count($child['children'])) { + $j ++; + } + + $moved_item = $child['children'][$j]; + unset($parent['children'][$i]['children'][$j]); + $parent['children'][] = $moved_item; + } else { + $parent['children'][$i] = smart_flatten_conversation($child); + } } } - $arr = $newarr; + return $parent; +} + + +/** + * Expands a flat list of items into corresponding tree-like conversation structures, + * sort the top-level posts either on "created" or "commented", and finally + * append all the items at the top level (???) + * + * @brief Expands a flat item list into a conversation array for display + * + * @param array $item_list A list of items belonging to one or more conversations + * @param string $order Either on "created" or "commented" + * @return array + */ +function conv_sort(array $item_list, $order) +{ + $parents = []; + + if (!(is_array($item_list) && count($item_list))) { + return $parents; + } + + $item_array = []; + + // Dedupes the item list on the uri to prevent infinite loops + foreach ($item_list as $item) { + $item_array[$item['uri']] = $item; + } - foreach ($arr as $x) { - if ($x['id'] == $x['parent']) { - $parents[] = $x; + // Extract the top level items + foreach ($item_array as $item) { + if ($item['id'] == $item['parent']) { + $parents[] = $item; } } @@ -1422,73 +1494,73 @@ function conv_sort($arr, $order) { usort($parents, 'sort_thr_commented'); } - if (count($parents)) { - foreach ($parents as $i => $_x) { - $parents[$i]['children'] = get_item_children($arr, $_x); - } + /* + * Plucks children from the item_array, second pass collects eventual orphan + * items and add them as children of their top-level post. + */ + foreach ($parents as $i => $parent) { + $parents[$i]['children'] = + array_merge(get_item_children($item_array, $parent, true), + get_item_children($item_array, $parent, false)); } - /// @TODO Old-lost code? - /*foreach ($arr as $x) { - if ($x['id'] != $x['parent']) { - $p = find_thread_parent_index($parents,$x); - if ($p !== false) - $parents[$p]['children'][] = $x; - } - }*/ - if (count($parents)) { - foreach ($parents as $k => $v) { - if (count($parents[$k]['children'])) { - $parents[$k]['children'] = sort_item_children($parents[$k]['children']); - /// @TODO Old-lost code? - /*$y = $parents[$k]['children']; - usort($y,'sort_thr_created_rev'); - $parents[$k]['children'] = $y;*/ - } + foreach ($parents as $i => $parent) { + $parents[$i]['children'] = sort_item_children($parents[$i]['children']); + } + + if (PConfig::get(local_user(), 'system', 'smart_threading', 0)) { + foreach ($parents as $i => $parent) { + $parents[$i] = smart_flatten_conversation($parent); } } - $ret = array(); - if (count($parents)) { - foreach ($parents as $x) { - $ret[] = $x; - if (count($x['children'])) { - add_children_to_list($x['children'], $ret); - /// @TODO Old-lost code? - /*foreach ($x['children'] as $y) - $ret[] = $y;*/ - } + /// @TODO: Stop recusrsively adding all children back to the top level (!!!) + /// However, this apparently ensures responses (likes, attendance) display (?!) + foreach ($parents as $parent) { + if (count($parent['children'])) { + add_children_to_list($parent['children'], $parents); } } - return $ret; + return $parents; } -/// @TODO Add type-hint -function sort_thr_created($a, $b) { +/** + * @brief usort() callback to sort item arrays by the created key + * + * @param array $a + * @param array $b + * @return int + */ +function sort_thr_created(array $a, array $b) +{ return strcmp($b['created'], $a['created']); } -/// @TODO Add type-hint -function sort_thr_created_rev($a, $b) { +/** + * @brief usort() callback to reverse sort item arrays by the created key + * + * @param array $a + * @param array $b + * @return int + */ +function sort_thr_created_rev(array $a, array $b) +{ return strcmp($a['created'], $b['created']); } -/// @TODO Add type-hint -function sort_thr_commented($a, $b) { +/** + * @brief usort() callback to sort item arrays by the commented key + * + * @param array $a + * @param array $b + * @return type + */ +function sort_thr_commented(array $a, array $b) +{ return strcmp($b['commented'], $a['commented']); } -/// @TODO Add type-hint -function find_thread_parent_index($arr, $x) { - foreach ($arr as $k => $v) { - if ($v['id'] == $x['parent']) { - return $k; - } - } - return false; -} - /// @TODO Add type-hint function render_location_dummy($item) { if ($item['location'] != "") { @@ -1511,7 +1583,7 @@ function get_responses($conv_responses, $response_verbs, $ob, $item) { if (count($ret[$v]['list']) > MAX_LIKERS) { $ret[$v]['list_part'] = array_slice($ret[$v]['list'], 0, MAX_LIKERS); array_push($ret[$v]['list_part'], '' . t('View all') . ''); + . (($ob) ? $ob->getId() : $item['id']) . '">' . t('View all') . ''); } else { $ret[$v]['list_part'] = ''; }