<?php
/**
- * @copyright Copyright (C) 2020, Friendica
+ * @copyright Copyright (C) 2010-2021, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
*/
use Friendica\App;
+use Friendica\BaseModule;
use Friendica\Content\ContactSelector;
use Friendica\Content\Feature;
-use Friendica\Content\Text\BBCode;
+use Friendica\Core\ACL;
use Friendica\Core\Hook;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Model\Contact;
use Friendica\Model\Item;
use Friendica\Model\Post;
-use Friendica\Model\Profile;
use Friendica\Model\Tag;
+use Friendica\Model\User;
use Friendica\Model\Verb;
-use Friendica\Object\Post as ObjectPost;
+use Friendica\Object\Post as PostObject;
use Friendica\Object\Thread;
use Friendica\Protocol\Activity;
use Friendica\Util\Crypto;
use Friendica\Util\DateTimeFormat;
+use Friendica\Util\Proxy;
use Friendica\Util\Strings;
use Friendica\Util\Temporal;
use Friendica\Util\XML;
-function item_extract_images($body) {
-
- $saved_image = [];
- $orig_body = $body;
- $new_body = '';
-
- $cnt = 0;
- $img_start = strpos($orig_body, '[img');
- $img_st_close = ($img_start !== false ? strpos(substr($orig_body, $img_start), ']') : false);
- $img_end = ($img_start !== false ? strpos(substr($orig_body, $img_start), '[/img]') : false);
- while (($img_st_close !== false) && ($img_end !== false)) {
-
- $img_st_close++; // make it point to AFTER the closing bracket
- $img_end += $img_start;
-
- if (!strcmp(substr($orig_body, $img_start + $img_st_close, 5), 'data:')) {
- // This is an embedded image
-
- $saved_image[$cnt] = substr($orig_body, $img_start + $img_st_close, $img_end - ($img_start + $img_st_close));
- $new_body = $new_body . substr($orig_body, 0, $img_start) . '[!#saved_image' . $cnt . '#!]';
-
- $cnt++;
- } else {
- $new_body = $new_body . substr($orig_body, 0, $img_end + strlen('[/img]'));
- }
-
- $orig_body = substr($orig_body, $img_end + strlen('[/img]'));
-
- if ($orig_body === false) {
- // in case the body ends on a closing image tag
- $orig_body = '';
- }
-
- $img_start = strpos($orig_body, '[img');
- $img_st_close = ($img_start !== false ? strpos(substr($orig_body, $img_start), ']') : false);
- $img_end = ($img_start !== false ? strpos(substr($orig_body, $img_start), '[/img]') : false);
- }
-
- $new_body = $new_body . $orig_body;
-
- return ['body' => $new_body, 'images' => $saved_image];
-}
-
-function item_redir_and_replace_images($body, $images, $cid) {
-
- $origbody = $body;
- $newbody = '';
-
- $cnt = 1;
- $pos = BBCode::getTagPosition($origbody, 'url', 0);
- while ($pos !== false && $cnt < 1000) {
-
- $search = '/\[url\=(.*?)\]\[!#saved_image([0-9]*)#!\]\[\/url\]' . '/is';
- $replace = '[url=' . DI::baseUrl() . '/redir/' . $cid
- . '?url=' . '$1' . '][!#saved_image' . '$2' .'#!][/url]';
-
- $newbody .= substr($origbody, 0, $pos['start']['open']);
- $subject = substr($origbody, $pos['start']['open'], $pos['end']['close'] - $pos['start']['open']);
- $origbody = substr($origbody, $pos['end']['close']);
- if ($origbody === false) {
- $origbody = '';
- }
-
- $subject = preg_replace($search, $replace, $subject);
- $newbody .= $subject;
-
- $cnt++;
- // Isn't this supposed to use $cnt value for $occurrences? - @MrPetovan
- $pos = BBCode::getTagPosition($origbody, 'url', 0);
- }
- $newbody .= $origbody;
-
- $cnt = 0;
- foreach ($images as $image) {
- /*
- * We're depending on the property of 'foreach' (specified on the PHP website) that
- * it loops over the array starting from the first element and going sequentially
- * to the last element.
- */
- $newbody = str_replace('[!#saved_image' . $cnt . '#!]', '[img]' . $image . '[/img]', $newbody);
- $cnt++;
- }
- return $newbody;
-}
-
/**
* Render actions localized
*
*/
function localize_item(&$item)
{
- $extracted = item_extract_images($item['body']);
- if ($extracted['images']) {
- $item['body'] = item_redir_and_replace_images($extracted['body'], $extracted['images'], $item['contact-id']);
- }
-
- /// @todo The following functionality needs to be cleaned up.
+ DI::profiler()->startRecording('rendering');
+ /// @todo The following functionality needs to be cleaned up.
if (!empty($item['verb'])) {
$activity = DI::activity();
if (stristr($item['verb'], Activity::POKE)) {
$verb = urldecode(substr($item['verb'], strpos($item['verb'],'#') + 1));
if (!$verb) {
+ DI::profiler()->stopRecording();
return;
}
if ($item['object-type'] == "" || $item['object-type'] !== Activity\ObjectType::PERSON) {
+ DI::profiler()->stopRecording();
return;
}
- $Aname = $item['author-name'];
- $Alink = $item['author-link'];
-
$obj = XML::parseString($xmlhead . $item['object']);
$Bname = $obj->title;
}
}
- $A = '[url=' . Contact::magicLink($Alink) . ']' . $Aname . '[/url]';
- $B = '[url=' . Contact::magicLink($Blink) . ']' . $Bname . '[/url]';
- if ($Bphoto != "") {
+ $author = ['uid' => 0, 'id' => $item['author-id'],
+ 'network' => $item['author-network'], 'url' => $item['author-link']];
+ $A = '[url=' . Contact::magicLinkByContact($author) . ']' . $item['author-name'] . '[/url]';
+
+ if (!empty($Blink)) {
+ $B = '[url=' . Contact::magicLink($Blink) . ']' . $Bname . '[/url]';
+ } else {
+ $B = '';
+ }
+
+ if ($Bphoto != "" && !empty($Blink)) {
$Bphoto = '[url=' . Contact::magicLink($Blink) . '][img=80x80]' . $Bphoto . '[/img][/url]';
}
'verb', 'object-type', 'resource-id', 'body', 'plink'];
$obj = Post::selectFirst($fields, ['uri' => $item['parent-uri']]);
if (!DBA::isResult($obj)) {
+ DI::profiler()->stopRecording();
return;
}
}
}
- // add zrl's to public images
- $photo_pattern = "/\[url=(.*?)\/photos\/(.*?)\/image\/(.*?)\]\[img(.*?)\]h(.*?)\[\/img\]\[\/url\]/is";
- if (preg_match($photo_pattern, $item['body'])) {
- $photo_replace = '[url=' . Profile::zrl('$1' . '/photos/' . '$2' . '/image/' . '$3' , true) . '][img' . '$4' . ']h' . '$5' . '[/img][/url]';
- $item['body'] = BBCode::pregReplaceInTag($photo_pattern, $photo_replace, 'url', $item['body']);
- }
-
// add sparkle links to appropriate permalinks
- $author = ['uid' => 0, 'id' => $item['author-id'],
- 'network' => $item['author-network'], 'url' => $item['author-link']];
-
// Only create a redirection to a magic link when logged in
if (!empty($item['plink']) && Session::isAuthenticated()) {
+ $author = ['uid' => 0, 'id' => $item['author-id'],
+ 'network' => $item['author-network'], 'url' => $item['author-link']];
$item['plink'] = Contact::magicLinkByContact($author, $item['plink']);
}
+ DI::profiler()->stopRecording();
}
/**
*/
function conversation(App $a, array $items, $mode, $update, $preview = false, $order = 'commented', $uid = 0)
{
+ DI::profiler()->startRecording('rendering');
$page = DI::page();
$page->registerFooterScript(Theme::getPathForFile('asset/typeahead.js/dist/typeahead.bundle.js'));
$ssl_state = (local_user() ? true : false);
- $profile_owner = 0;
$live_update_div = '';
$blocklist = conv_get_blocklist();
if ($mode === 'network') {
$items = conversation_add_children($items, false, $order, $uid);
- $profile_owner = local_user();
if (!$update) {
/*
* The special div is needed for liveUpdate to kick in for this page.
. "'; </script>\r\n";
}
} elseif ($mode === 'profile') {
- $items = conversation_add_children($items, false, $order, $uid);
- $profile_owner = $a->profile['uid'];
+ $items = conversation_add_children($items, false, $order, local_user());
if (!$update) {
$tab = 'posts';
*/
$live_update_div = '<div id="live-profile"></div>' . "\r\n"
- . "<script> var profile_uid = " . $a->profile['uid']
+ . "<script> var profile_uid = " . $uid
. "; var netargs = '?f='; </script>\r\n";
}
}
} elseif ($mode === 'notes') {
$items = conversation_add_children($items, false, $order, local_user());
- $profile_owner = local_user();
if (!$update) {
$live_update_div = '<div id="live-notes"></div>' . "\r\n"
}
} elseif ($mode === 'display') {
$items = conversation_add_children($items, false, $order, $uid);
- $profile_owner = $a->profile['uid'];
if (!$update) {
$live_update_div = '<div id="live-display"></div>' . "\r\n"
}
} elseif ($mode === 'community') {
$items = conversation_add_children($items, true, $order, $uid);
- $profile_owner = 0;
if (!$update) {
$live_update_div = '<div id="live-community"></div>' . "\r\n"
}
} elseif ($mode === 'contacts') {
$items = conversation_add_children($items, false, $order, $uid);
- $profile_owner = 0;
if (!$update) {
$live_update_div = '<div id="live-contact"></div>' . "\r\n"
$live_update_div = '<div id="live-search"></div>' . "\r\n";
}
- $page_dropping = ((local_user() && local_user() == $profile_owner) ? true : false);
+ $page_dropping = ((local_user() && local_user() == $uid) ? true : false);
if (!$update) {
$_SESSION['return_path'] = DI::args()->getQueryString();
'attendyes' => [],
'attendno' => [],
'attendmaybe' => [],
- 'announce' => [],
+ 'announce' => [],
];
if (DI::pConfig()->get(local_user(), 'system', 'hide_dislike')) {
$threadsid = -1;
$page_template = Renderer::getMarkupTemplate("conversation.tpl");
+ $formSecurityToken = BaseModule::getFormSecurityToken('contact_action');
if (!empty($items)) {
- if (in_array($mode, ['community', 'contacts'])) {
+ if (in_array($mode, ['community', 'contacts', 'profile'])) {
$writable = true;
} else {
$writable = ($items[0]['uid'] == 0) && in_array($items[0]['network'], Protocol::FEDERATED);
$tpl = 'search_item.tpl';
+ $uriids = [];
+
foreach ($items as $item) {
+ if (in_array($item['uri-id'], $uriids)) {
+ continue;
+ }
+
+ $uriids[] = $item['uri-id'];
if (!visible_activity($item)) {
continue;
$body_html = Item::prepareBody($item, true, $preview);
- list($categories, $folders) = DI::contentItem()->determineCategoriesTerms($item);
+ list($categories, $folders) = DI::contentItem()->determineCategoriesTerms($item, local_user());
if (!empty($item['content-warning']) && DI::pConfig()->get(local_user(), 'system', 'disable_cw', false)) {
$title = ucfirst($item['content-warning']);
'network_icon' => ContactSelector::networkToIcon($item['network'], $item['author-link']),
'linktitle' => DI::l10n()->t('View %s\'s profile @ %s', $profile_name, $item['author-link']),
'profile_url' => $profile_link,
- 'item_photo_menu_html' => item_photo_menu($item),
+ 'item_photo_menu_html' => item_photo_menu($item, $formSecurityToken),
'name' => $profile_name,
'sparkle' => $sparkle,
'lock' => false,
- 'thumb' => DI::baseUrl()->remove($item['author-avatar']),
+ 'thumb' => DI::baseUrl()->remove(Contact::getAvatarUrlForUrl($item['author-link'], $item['uid'], Proxy::SIZE_THUMB)),
'title' => $title,
'body_html' => $body_html,
'tags' => $tags['tags'],
'indent' => '',
'owner_name' => '',
'owner_url' => '',
- 'owner_photo' => DI::baseUrl()->remove($item['owner-avatar']),
+ 'owner_photo' => DI::baseUrl()->remove(Contact::getAvatarUrlForUrl($item['owner-link'], $item['uid'], Proxy::SIZE_THUMB)),
'plink' => Item::getPlink($item),
'edpost' => false,
'isstarred' => 'unstarred',
$item['pagedrop'] = $page_dropping;
if ($item['gravity'] == GRAVITY_PARENT) {
- $item_object = new ObjectPost($item);
+ $item_object = new PostObject($item);
$conv->addParent($item_object);
}
}
- $threads = $conv->getTemplateData($conv_responses);
+ $threads = $conv->getTemplateData($conv_responses, $formSecurityToken);
if (!$threads) {
Logger::log('[ERROR] conversation : Failed to get template data.', Logger::DEBUG);
$threads = [];
'$remove' => DI::l10n()->t('remove'),
'$mode' => $mode,
'$update' => $update,
- '$user' => $a->user,
'$threads' => $threads,
'$dropping' => ($page_dropping ? DI::l10n()->t('Delete Selected Items') : False),
]);
+ DI::profiler()->stopRecording();
return $o;
}
/**
- * Fetch all comments from a query. Additionally set the newest resharer as thread owner.
+ * Adds some information (Causer, post reason, direction) to the fetched post row.
*
- * @param mixed $thread_items Database statement with thread posts
- * @param boolean $pinned Is the item pinned?
- * @param array $activity Contact data of the resharer
+ * @param array $row Post row
+ * @param array $activity Contact data of the resharer
*
* @return array items with parents and comments
*/
-function conversation_fetch_comments($thread_items, bool $pinned, array $activity) {
- $comments = [];
-
- while ($row = Item::fetch($thread_items)) {
- if (!empty($activity)) {
- if (($row['gravity'] == GRAVITY_PARENT)) {
- $row['post-type'] = Item::PT_ANNOUNCEMENT;
- $row = array_merge($row, $activity);
- $contact = Contact::getById($activity['causer-id'], ['url', 'name', 'thumb']);
- $row['causer-link'] = $contact['url'];
- $row['causer-avatar'] = $contact['thumb'];
- $row['causer-name'] = $contact['name'];
- } elseif (($row['gravity'] == GRAVITY_ACTIVITY) && ($row['verb'] == Activity::ANNOUNCE) &&
- ($row['author-id'] == $activity['causer-id'])) {
- continue;
- }
- }
+function conversation_add_row_information(array $row, array $activity) {
+ DI::profiler()->startRecording('rendering');
- $name = $row['causer-contact-type'] == Contact::TYPE_RELAY ? $row['causer-link'] : $row['causer-name'];
+ if ($row['uid'] == 0) {
+ $row['writable'] = in_array($row['network'], Protocol::FEDERATED);
+ }
- switch ($row['post-type']) {
- case Item::PT_TO:
- $row['direction'] = ['direction' => 7, 'title' => DI::l10n()->t('You had been addressed (%s).', 'to')];
- break;
- case Item::PT_CC:
- $row['direction'] = ['direction' => 7, 'title' => DI::l10n()->t('You had been addressed (%s).', 'cc')];
- break;
- case Item::PT_BTO:
- $row['direction'] = ['direction' => 7, 'title' => DI::l10n()->t('You had been addressed (%s).', 'bto')];
- break;
- case Item::PT_BCC:
- $row['direction'] = ['direction' => 7, 'title' => DI::l10n()->t('You had been addressed (%s).', 'bcc')];
- break;
- case Item::PT_FOLLOWER:
- $row['direction'] = ['direction' => 6, 'title' => DI::l10n()->t('You are following %s.', $row['author-name'])];
- break;
- case Item::PT_TAG:
- $row['direction'] = ['direction' => 4, 'title' => DI::l10n()->t('Tagged')];
- break;
- case Item::PT_ANNOUNCEMENT:
- if (!empty($row['causer-id']) && DI::pConfig()->get(local_user(), 'system', 'display_resharer')) {
- $row['owner-id'] = $row['causer-id'];
- $row['owner-link'] = $row['causer-link'];
- $row['owner-avatar'] = $row['causer-avatar'];
- $row['owner-name'] = $row['causer-name'];
- }
+ if (!empty($activity)) {
+ if (($row['gravity'] == GRAVITY_PARENT)) {
+ $row['post-reason'] = Item::PR_ANNOUNCEMENT;
+ $row = array_merge($row, $activity);
+ $contact = Contact::getById($activity['causer-id'], ['url', 'name', 'thumb']);
+ $row['causer-link'] = $contact['url'];
+ $row['causer-avatar'] = $contact['thumb'];
+ $row['causer-name'] = $contact['name'];
+ } elseif (($row['gravity'] == GRAVITY_ACTIVITY) && ($row['verb'] == Activity::ANNOUNCE) &&
+ ($row['author-id'] == $activity['causer-id'])) {
+ return $row;
+ }
+ }
- if (($row['gravity'] == GRAVITY_PARENT) && !empty($row['causer-id'])) {
- $row['reshared'] = DI::l10n()->t('%s reshared this.', '<a href="'. htmlentities(Contact::magicLinkById($row['causer-id'])) .'">' . htmlentities($name) . '</a>');
- }
- $row['direction'] = ['direction' => 3, 'title' => (empty($row['causer-id']) ? DI::l10n()->t('Reshared') : DI::l10n()->t('Reshared by %s', $name))];
- break;
- case Item::PT_COMMENT:
- $row['direction'] = ['direction' => 5, 'title' => DI::l10n()->t('%s is participating in this thread.', $row['author-name'])];
- break;
- case Item::PT_STORED:
- $row['direction'] = ['direction' => 8, 'title' => DI::l10n()->t('Stored')];
- break;
- case Item::PT_GLOBAL:
- $row['direction'] = ['direction' => 9, 'title' => DI::l10n()->t('Global')];
- break;
- case Item::PT_RELAY:
- $row['direction'] = ['direction' => 10, 'title' => (empty($row['causer-id']) ? DI::l10n()->t('Relayed') : DI::l10n()->t('Relayed by %s.', $name))];
- break;
- case Item::PT_FETCHED:
- $row['direction'] = ['direction' => 2, 'title' => (empty($row['causer-id']) ? DI::l10n()->t('Fetched') : DI::l10n()->t('Fetched because of %s', $name))];
- break;
+ switch ($row['post-reason']) {
+ case Item::PR_TO:
+ $row['direction'] = ['direction' => 7, 'title' => DI::l10n()->t('You had been addressed (%s).', 'to')];
+ break;
+ case Item::PR_CC:
+ $row['direction'] = ['direction' => 7, 'title' => DI::l10n()->t('You had been addressed (%s).', 'cc')];
+ break;
+ case Item::PR_BTO:
+ $row['direction'] = ['direction' => 7, 'title' => DI::l10n()->t('You had been addressed (%s).', 'bto')];
+ break;
+ case Item::PR_BCC:
+ $row['direction'] = ['direction' => 7, 'title' => DI::l10n()->t('You had been addressed (%s).', 'bcc')];
+ break;
+ case Item::PR_FOLLOWER:
+ $row['direction'] = ['direction' => 6, 'title' => DI::l10n()->t('You are following %s.', $row['author-name'])];
+ break;
+ case Item::PR_TAG:
+ $row['direction'] = ['direction' => 4, 'title' => DI::l10n()->t('Tagged')];
+ break;
+ case Item::PR_ANNOUNCEMENT:
+ if (!empty($row['causer-id']) && DI::pConfig()->get(local_user(), 'system', 'display_resharer')) {
+ $row['owner-id'] = $row['causer-id'];
+ $row['owner-link'] = $row['causer-link'];
+ $row['owner-avatar'] = $row['causer-avatar'];
+ $row['owner-name'] = $row['causer-name'];
}
- if ($row['gravity'] == GRAVITY_PARENT) {
- $row['pinned'] = $pinned;
- }
-
- $comments[] = $row;
+ if (($row['gravity'] == GRAVITY_PARENT) && !empty($row['causer-id'])) {
+ $causer = ['uid' => 0, 'id' => $row['causer-id'],
+ 'network' => $row['causer-network'], 'url' => $row['causer-link']];
+ $row['reshared'] = DI::l10n()->t('%s reshared this.', '<a href="'. htmlentities(Contact::magicLinkByContact($causer)) .'">' . htmlentities($row['causer-name']) . '</a>');
+ }
+ $row['direction'] = ['direction' => 3, 'title' => (empty($row['causer-id']) ? DI::l10n()->t('Reshared') : DI::l10n()->t('Reshared by %s <%s>', $row['causer-name'], $row['causer-link']))];
+ break;
+ case Item::PR_COMMENT:
+ $row['direction'] = ['direction' => 5, 'title' => DI::l10n()->t('%s is participating in this thread.', $row['author-name'])];
+ break;
+ case Item::PR_STORED:
+ $row['direction'] = ['direction' => 8, 'title' => DI::l10n()->t('Stored')];
+ break;
+ case Item::PR_GLOBAL:
+ $row['direction'] = ['direction' => 9, 'title' => DI::l10n()->t('Global')];
+ break;
+ case Item::PR_RELAY:
+ $row['direction'] = ['direction' => 10, 'title' => (empty($row['causer-id']) ? DI::l10n()->t('Relayed') : DI::l10n()->t('Relayed by %s <%s>', $row['causer-name'], $row['causer-link']))];
+ break;
+ case Item::PR_FETCHED:
+ $row['direction'] = ['direction' => 2, 'title' => (empty($row['causer-id']) ? DI::l10n()->t('Fetched') : DI::l10n()->t('Fetched because of %s <%s>', $row['causer-name'], $row['causer-link']))];
+ break;
}
- DBA::close($thread_items);
-
- return $comments;
+ DI::profiler()->stopRecording();
+ return $row;
}
/**
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function conversation_add_children(array $parents, $block_authors, $order, $uid) {
+ DI::profiler()->startRecording('rendering');
if (count($parents) > 1) {
$max_comments = DI::config()->get('system', 'max_comments', 100);
} else {
$max_comments = DI::config()->get('system', 'max_display_comments', 1000);
}
- $params = ['order' => ['gravity', 'uid', 'commented' => true]];
+ $params = ['order' => ['uri-id' => true, 'uid' => true]];
- if ($max_comments > 0) {
- $params['limit'] = $max_comments;
- }
-
- $items = [];
+ $activities = [];
+ $uriids = [];
+ $commentcounter = [];
+ $activitycounter = [];
foreach ($parents AS $parent) {
if (!empty($parent['thr-parent-id']) && !empty($parent['gravity']) && ($parent['gravity'] == GRAVITY_ACTIVITY)) {
- $condition = ["`item`.`parent-uri-id` = ? AND `item`.`uid` IN (0, ?) AND (`vid` != ? OR `vid` IS NULL)",
- $parent['thr-parent-id'], $uid, Verb::getID(Activity::FOLLOW)];
+ $uriid = $parent['thr-parent-id'];
if (!empty($parent['author-id'])) {
- $activity = ['causer-id' => $parent['author-id']];
+ $activities[$uriid] = ['causer-id' => $parent['author-id']];
foreach (['commented', 'received', 'created'] as $orderfields) {
if (!empty($parent[$orderfields])) {
- $activity[$orderfields] = $parent[$orderfields];
- }
+ $activities[$uriid][$orderfields] = $parent[$orderfields];
+ }
}
}
} else {
- $condition = ["`item`.`parent-uri` = ? AND `item`.`uid` IN (0, ?) AND (`vid` != ? OR `vid` IS NULL)",
- $parent['uri'], $uid, Verb::getID(Activity::FOLLOW)];
- $activity = [];
+ $uriid = $parent['uri-id'];
}
- $items = conversation_fetch_items($parent, $items, $condition, $block_authors, $params, $activity);
+ $uriids[] = $uriid;
+
+ $commentcounter[$uriid] = 0;
+ $activitycounter[$uriid] = 0;
}
- foreach ($items as $index => $item) {
- if ($item['uid'] == 0) {
- $items[$index]['writable'] = in_array($item['network'], Protocol::FEDERATED);
- }
+ $condition = ['parent-uri-id' => $uriids];
+ if ($block_authors) {
+ $condition['author-hidden'] = false;
}
- $items = conv_sort($items, $order);
+ $condition = DBA::mergeConditions($condition,
+ ["`uid` IN (0, ?) AND (`vid` != ? OR `vid` IS NULL)", $uid, Verb::getID(Activity::FOLLOW)]);
- return $items;
-}
+ $thread_items = Post::selectForUser(local_user(), array_merge(Item::DISPLAY_FIELDLIST, ['pinned', 'contact-uid', 'gravity', 'post-type', 'post-reason']), $condition, $params);
-/**
- * Fetch conversation items
- *
- * @param array $parent Parent Item array
- * @param array $items Item array
- * @param array $condition SQL condition
- * @param boolean $block_authors Don't show posts from contacts that are hidden (used on the community page)
- * @param array $params SQL parameters
- * @param array $activity Contact data of the resharer
- * @return array
- */
-function conversation_fetch_items(array $parent, array $items, array $condition, bool $block_authors, array $params, array $activity) {
- if ($block_authors) {
- $condition[0] .= " AND NOT `author`.`hidden`";
+ $items = [];
+
+ while ($row = Post::fetch($thread_items)) {
+ if (!empty($items[$row['uri-id']]) && ($row['uid'] == 0)) {
+ continue;
+ }
+
+ if ($max_comments > 0) {
+ if (($row['gravity'] == GRAVITY_COMMENT) && (++$commentcounter[$row['parent-uri-id']] > $max_comments)) {
+ continue;
+ }
+ if (($row['gravity'] == GRAVITY_ACTIVITY) && (++$activitycounter[$row['parent-uri-id']] > $max_comments)) {
+ continue;
+ }
+ }
+ $items[$row['uri-id']] = conversation_add_row_information($row, $activities[$row['uri-id']] ?? []);
}
- $thread_items = Item::selectForUser(local_user(), array_merge(Item::DISPLAY_FIELDLIST, ['pinned', 'contact-uid', 'gravity', 'post-type']), $condition, $params);
+ DBA::close($thread_items);
- $comments = conversation_fetch_comments($thread_items, $parent['pinned'] ?? false, $activity);
+ $items = conv_sort($items, $order);
- if (count($comments) != 0) {
- $items = array_merge($items, $comments);
- }
+ DI::profiler()->stopRecording();
return $items;
}
-function item_photo_menu($item) {
+function item_photo_menu($item, string $formSecurityToken)
+{
+ DI::profiler()->startRecording('rendering');
$sub_link = '';
$poke_link = '';
$contact_url = '';
$block_link = '';
$ignore_link = '';
- if (local_user() && local_user() == $item['uid'] && $item['gravity'] == GRAVITY_PARENT && !$item['self']) {
- $sub_link = 'javascript:dosubthread(' . $item['id'] . '); return false;';
+ if (local_user() && local_user() == $item['uid'] && $item['gravity'] == GRAVITY_PARENT && !$item['self'] && !$item['mention']) {
+ $sub_link = 'javascript:doFollowThread(' . $item['id'] . '); return false;';
}
$author = ['uid' => 0, 'id' => $item['author-id'],
$sparkle = (strpos($profile_link, 'redir/') === 0);
$cid = 0;
- $pcid = Contact::getIdForURL($item['author-link'], 0, false);
+ $pcid = $item['author-id'];
$network = '';
$rel = 0;
$condition = ['uid' => local_user(), 'nurl' => Strings::normaliseLink($item['author-link'])];
if (!empty($pcid)) {
$contact_url = 'contact/' . $pcid;
$posts_link = $contact_url . '/posts';
- $block_link = $contact_url . '/block';
- $ignore_link = $contact_url . '/ignore';
+ $block_link = $item['self'] ? '' : $contact_url . '/block?t=' . $formSecurityToken;
+ $ignore_link = $item['self'] ? '' : $contact_url . '/ignore?t=' . $formSecurityToken;
}
if ($cid && !$item['self']) {
if (strpos($v, 'javascript:') === 0) {
$v = substr($v, 11);
$o .= '<li role="menuitem"><a onclick="' . $v . '">' . $k . '</a></li>' . PHP_EOL;
- } elseif ($v!='') {
+ } elseif ($v) {
$o .= '<li role="menuitem"><a href="' . $v . '">' . $k . '</a></li>' . PHP_EOL;
}
}
+ DI::profiler()->stopRecording();
return $o;
}
$link = '<a href="' . $url . '"' . $sparkle . '>' . htmlentities($activity['author-name']) . '</a>';
- if (empty($activity['thr-parent'])) {
- $activity['thr-parent'] = $activity['parent-uri'];
+ if (empty($activity['thr-parent-id'])) {
+ $activity['thr-parent-id'] = $activity['parent-uri-id'];
}
// Skip when the causer of the parent is the same than the author of the announce
- if (($verb == Activity::ANNOUNCE) && Post::exists(['uri' => $activity['thr-parent'],
+ if (($verb == Activity::ANNOUNCE) && Post::exists(['uri-id' => $activity['thr-parent-id'],
'uid' => $activity['uid'], 'causer-id' => $activity['author-id'], 'gravity' => GRAVITY_PARENT])) {
continue;
}
- if (!isset($conv_responses[$mode][$activity['thr-parent']])) {
- $conv_responses[$mode][$activity['thr-parent']] = [
+ if (!isset($conv_responses[$mode][$activity['thr-parent-id']])) {
+ $conv_responses[$mode][$activity['thr-parent-id']] = [
'links' => [],
'self' => 0,
];
- } elseif (in_array($link, $conv_responses[$mode][$activity['thr-parent']]['links'])) {
+ } elseif (in_array($link, $conv_responses[$mode][$activity['thr-parent-id']]['links'])) {
// only list each unique author once
continue;
}
if (public_contact() == $activity['author-id']) {
- $conv_responses[$mode][$activity['thr-parent']]['self'] = 1;
+ $conv_responses[$mode][$activity['thr-parent-id']]['self'] = 1;
}
- $conv_responses[$mode][$activity['thr-parent']]['links'][] = $link;
+ $conv_responses[$mode][$activity['thr-parent-id']]['links'][] = $link;
// there can only be one activity verb per item so if we found anything, we can stop looking
return;
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function format_activity(array $links, $verb, $id) {
+ DI::profiler()->startRecording('rendering');
$o = '';
$expanded = '';
$phrase = '';
]);
$o .= $expanded;
+ DI::profiler()->stopRecording();
return $o;
}
-function status_editor(App $a, $x, $notes_cid = 0, $popup = false)
+function status_editor(App $a, array $x = [], $notes_cid = 0, $popup = false)
{
+ $user = User::getById($a->getLoggedInUserId(), ['uid', 'nickname', 'allow_location', 'default-location']);
+ if (empty($user['uid'])) {
+ return '';
+ }
+
+ DI::profiler()->startRecording('rendering');
$o = '';
+ $x['allow_location'] = $x['allow_location'] ?? $user['allow_location'];
+ $x['default_location'] = $x['default_location'] ?? $user['default-location'];
+ $x['nickname'] = $x['nickname'] ?? $user['nickname'];
+ $x['lockstate'] = $x['lockstate'] ?? ACL::getLockstateForUserId($user['uid']) ? 'lock' : 'unlock';
+ $x['acl'] = $x['acl'] ?? ACL::getFullSelectorHTML(DI::page(), $user['uid'], true);
+ $x['bang'] = $x['bang'] ?? '';
+ $x['visitor'] = $x['visitor'] ?? 'block';
+ $x['is_owner'] = $x['is_owner'] ?? true;
+ $x['profile_uid'] = $x['profile_uid'] ?? local_user();
+
+
$geotag = !empty($x['allow_location']) ? Renderer::replaceMacros(Renderer::getMarkupTemplate('jot_geotag.tpl'), []) : '';
$tpl = Renderer::getMarkupTemplate('jot-header.tpl');
'$edimg' => DI::l10n()->t('Image'),
'$edurl' => DI::l10n()->t('Link'),
'$edattach' => DI::l10n()->t('Link or Media'),
+ '$edvideo' => DI::l10n()->t('Video'),
'$setloc' => DI::l10n()->t('Set your location'),
'$shortsetloc' => DI::l10n()->t('set location'),
'$noloc' => DI::l10n()->t('Clear browser location'),
'$placeholdertitle' => DI::l10n()->t('Set title'),
'$category' => $x['category'] ?? '',
'$placeholdercategory' => Feature::isEnabled(local_user(), 'categories') ? DI::l10n()->t("Categories \x28comma-separated list\x29") : '',
+ '$scheduled_at' => Temporal::getDateTimeField(
+ new DateTime(),
+ new DateTime('now + 6 months'),
+ null,
+ DI::l10n()->t('Scheduled at'),
+ 'scheduled_at'
+ ),
'$wait' => DI::l10n()->t('Please wait'),
'$permset' => DI::l10n()->t('Permission settings'),
'$shortpermset' => DI::l10n()->t('Permissions'),
'$preview' => DI::l10n()->t('Preview'),
'$jotplugins' => $jotplugins,
'$notes_cid' => $notes_cid,
- '$sourceapp' => DI::l10n()->t($a->sourcename),
'$cancel' => DI::l10n()->t('Cancel'),
'$rand_num' => Crypto::randomDigits(12),
$o = '<div id="jot-popup" style="display: none;">' . $o . '</div>';
}
+ DI::profiler()->stopRecording();
return $o;
}
*/
function get_item_children(array &$item_list, array $parent, $recursive = true)
{
+ DI::profiler()->startRecording('rendering');
$children = [];
foreach ($item_list as $i => $item) {
if ($item['gravity'] != GRAVITY_PARENT) {
if ($recursive) {
// Fallback to parent-uri if thr-parent is not set
- $thr_parent = $item['thr-parent'];
+ $thr_parent = $item['thr-parent-id'];
if ($thr_parent == '') {
- $thr_parent = $item['parent-uri'];
+ $thr_parent = $item['parent-uri-id'];
}
- if ($thr_parent == $parent['uri']) {
+ if ($thr_parent == $parent['uri-id']) {
$item['children'] = get_item_children($item_list, $item);
$children[] = $item;
unset($item_list[$i]);
}
- } elseif ($item['parent'] == $parent['id']) {
+ } elseif ($item['parent-uri-id'] == $parent['uri-id']) {
$children[] = $item;
unset($item_list[$i]);
}
}
}
+ DI::profiler()->stopRecording();
return $children;
}
*/
function sort_item_children(array $items)
{
+ DI::profiler()->startRecording('rendering');
$result = $items;
usort($result, 'sort_thr_received_rev');
foreach ($result as $k => $i) {
$result[$k]['children'] = sort_item_children($result[$k]['children']);
}
}
+ DI::profiler()->stopRecording();
return $result;
}
*/
function smart_flatten_conversation(array $parent)
{
+ DI::profiler()->startRecording('rendering');
if (!isset($parent['children']) || count($parent['children']) == 0) {
+ DI::profiler()->stopRecording();
return $parent;
}
if (isset($child['children']) && count($child['children'])) {
// This helps counting only the regular posts
$count_post_closure = function($var) {
+ DI::profiler()->stopRecording();
return $var['verb'] === Activity::POST;
};
}
}
+ DI::profiler()->stopRecording();
return $parent;
}
*/
function conv_sort(array $item_list, $order)
{
+ DI::profiler()->startRecording('rendering');
$parents = [];
if (!(is_array($item_list) && count($item_list))) {
+ DI::profiler()->stopRecording();
return $parents;
}
continue;
}
- $item_array[$item['uri']] = $item;
+ $item_array[$item['uri-id']] = $item;
}
// Extract the top level items
}
}
+ DI::profiler()->stopRecording();
return $parents;
}