use Friendica\DI;
use Friendica\Model\Contact;
use Friendica\Model\Item;
+use Friendica\Model\Post;
use Friendica\Model\Profile;
use Friendica\Model\Tag;
use Friendica\Model\Verb;
-use Friendica\Object\Post;
+use Friendica\Object\Post as ObjectPost;
use Friendica\Object\Thread;
use Friendica\Protocol\Activity;
use Friendica\Util\Crypto;
if ($activity->match($item['verb'], Activity::TAG)) {
$fields = ['author-id', 'author-link', 'author-name', 'author-network',
'verb', 'object-type', 'resource-id', 'body', 'plink'];
- $obj = Item::selectFirst($fields, ['uri' => $item['parent-uri']]);
+ $obj = Post::selectFirst($fields, ['uri' => $item['parent-uri']]);
if (!DBA::isResult($obj)) {
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]';
+ $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']);
}
$blocklist = [];
foreach (explode(',', $str_blocked) as $entry) {
- // The 4th parameter guarantees that there always will be a public contact entry
- $cid = Contact::getIdForURL(trim($entry), 0, false, ['url' => trim($entry)]);
+ $cid = Contact::getIdForURL(trim($entry), 0, false);
if (!empty($cid)) {
$blocklist[] = $cid;
}
if (!$update) {
$live_update_div = '<div id="live-community"></div>' . "\r\n"
. "<script> var profile_uid = -1; var netargs = '" . substr(DI::args()->getCommand(), 10)
- ."/?f='; </script>\r\n";
+ . '?f='
+ . (!empty($_GET['no_sharer']) ? '&no_sharer=' . rawurlencode($_GET['no_sharer']) : '')
+ . "'; </script>\r\n";
}
} elseif ($mode === 'contacts') {
$items = conversation_add_children($items, false, $order, $uid);
$profile_owner = 0;
if (!$update) {
- $live_update_div = '<div id="live-contacts"></div>' . "\r\n"
- . "<script> var profile_uid = -1; var netargs = '" . substr(DI::args()->getCommand(), 9)
+ $live_update_div = '<div id="live-contact"></div>' . "\r\n"
+ . "<script> var profile_uid = -1; var netargs = '" . substr(DI::args()->getCommand(), 8)
."/?f='; </script>\r\n";
}
} elseif ($mode === 'search') {
}
$cb = ['items' => $items, 'mode' => $mode, 'update' => $update, 'preview' => $preview];
- Hook::callAll('conversation_start',$cb);
+ Hook::callAll('conversation_start', $cb);
$items = $cb['items'];
$writable = false;
}
- if (in_array($mode, ['network-new', 'search', 'contact-posts'])) {
+ if (in_array($mode, ['filed', 'search', 'contact-posts'])) {
/*
* "New Item View" on network page or search page results
}
$locate = ['location' => $item['location'], 'coord' => $item['coord'], 'html' => ''];
- Hook::callAll('render_location',$locate);
+ Hook::callAll('render_location', $locate);
$location_html = $locate['html'] ?: Strings::escapeHtml($locate['location'] ?: $locate['coord'] ?: '');
localize_item($item);
- if ($mode === 'network-new') {
+ if ($mode === 'filed') {
$dropping = true;
} else {
$dropping = false;
];
$likebuttons = [
- 'like' => null,
- 'dislike' => null,
- 'share' => null,
+ 'like' => null,
+ 'dislike' => null,
+ 'share' => null,
+ 'announce' => null,
];
if (DI::pConfig()->get(local_user(), 'system', 'hide_dislike')) {
'template' => $tpl,
'id' => ($preview ? 'P0' : $item['id']),
'guid' => ($preview ? 'Q0' : $item['guid']),
+ 'commented' => $item['commented'],
+ 'received' => $item['received'],
+ 'created_date' => $item['created'],
+ 'uriid' => $item['uri-id'],
'network' => $item['network'],
'network_name' => ContactSelector::networkToName($item['author-network'], $item['author-link'], $item['network']),
'network_icon' => ContactSelector::networkToIcon($item['network'], $item['author-link']),
'folders' => $folders,
'text' => strip_tags($body_html),
'localtime' => DateTimeFormat::local($item['created'], 'r'),
- 'ago' => (($item['app']) ? DI::l10n()->t('%s from %s', Temporal::getRelativeDate($item['created']),$item['app']) : Temporal::getRelativeDate($item['created'])),
+ 'ago' => (($item['app']) ? DI::l10n()->t('%s from %s', Temporal::getRelativeDate($item['created']), $item['app']) : Temporal::getRelativeDate($item['created'])),
'location_html' => $location_html,
'indent' => '',
'owner_name' => '',
$item['pagedrop'] = $page_dropping;
if ($item['gravity'] == GRAVITY_PARENT) {
- $item_object = new Post($item);
+ $item_object = new ObjectPost($item);
$conv->addParent($item_object);
}
}
'$live_update' => $live_update_div,
'$remove' => DI::l10n()->t('remove'),
'$mode' => $mode,
+ '$update' => $update,
'$user' => $a->user,
'$threads' => $threads,
'$dropping' => ($page_dropping ? DI::l10n()->t('Delete Selected Items') : False),
*
* @param mixed $thread_items Database statement with thread posts
* @param boolean $pinned Is the item pinned?
+ * @param array $activity Contact data of the resharer
*
* @return array items with parents and comments
*/
-function conversation_fetch_comments($thread_items, $pinned) {
+function conversation_fetch_comments($thread_items, bool $pinned, array $activity) {
$comments = [];
- $parentlines = [];
- $lineno = 0;
- $direction = [];
- $actor = [];
- $received = '';
while ($row = Item::fetch($thread_items)) {
- if (!empty($parentlines) && ($row['verb'] == Activity::ANNOUNCE)
- && ($row['thr-parent'] == $row['parent-uri']) && ($row['received'] > $received)
- && Contact::isSharing($row['author-id'], $row['uid'])) {
- $direction = ['direction' => 3, 'title' => DI::l10n()->t('%s reshared this.', $row['author-name'])];
-
- $author = ['uid' => 0, 'id' => $row['author-id'],
- 'network' => $row['author-network'], 'url' => $row['author-link']];
- $url = '<a href="'. htmlentities(Contact::magicLinkByContact($author)) .'">' . htmlentities($row['author-name']) . '</a>';
-
- $actor = ['url' => $url, 'link' => $row['author-link'], 'avatar' => $row['author-avatar'], 'name' => $row['author-name']];
- $received = $row['received'];
+ 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;
+ }
}
- if (!empty($parentlines) && empty($direction) && ($row['gravity'] == GRAVITY_COMMENT)
- && Contact::isSharing($row['author-id'], $row['uid'])) {
- $direction = ['direction' => 5, 'title' => DI::l10n()->t('%s commented on this.', $row['author-name'])];
- }
+ $name = $row['causer-contact-type'] == Contact::TYPE_RELAY ? $row['causer-link'] : $row['causer-name'];
switch ($row['post-type']) {
case Item::PT_TO:
$row['direction'] = ['direction' => 4, 'title' => DI::l10n()->t('Tagged')];
break;
case Item::PT_ANNOUNCEMENT:
- $row['direction'] = ['direction' => 3, 'title' => DI::l10n()->t('Reshared')];
+ 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) && !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'])];
case Item::PT_STORED:
$row['direction'] = ['direction' => 8, 'title' => DI::l10n()->t('Stored')];
break;
- }
-
- if (($row['gravity'] == GRAVITY_PARENT) && !$row['origin'] && ($row['author-id'] == $row['owner-id']) &&
- !Contact::isSharing($row['author-id'], $row['uid'])) {
- $parentlines[] = $lineno;
- }
+ 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;
+ }
if ($row['gravity'] == GRAVITY_PARENT) {
$row['pinned'] = $pinned;
}
$comments[] = $row;
- $lineno++;
}
DBA::close($thread_items);
- if (!empty($direction)) {
- foreach ($parentlines as $line) {
- $comments[$line]['direction'] = $direction;
- if (!empty($actor)) {
- $comments[$line]['reshared'] = DI::l10n()->t('%s reshared this.', $actor['url']);
- if (DI::pConfig()->get(local_user(), 'system', 'display_resharer') ) {
- $comments[$line]['owner-link'] = $actor['link'];
- $comments[$line]['owner-avatar'] = $actor['avatar'];
- $comments[$line]['owner-name'] = $actor['name'];
- }
- }
- }
- }
return $comments;
}
$items = [];
foreach ($parents AS $parent) {
- $condition = ["`item`.`parent-uri` = ? AND `item`.`uid` IN (0, ?) AND (`vid` != ? OR `vid` IS NULL)",
- $parent['uri'], $uid, Verb::getID(Activity::FOLLOW)];
- $items = conversation_fetch_items($parent, $items, $condition, $block_authors, $params);
+ 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)];
+ if (!empty($parent['author-id'])) {
+ $activity = ['causer-id' => $parent['author-id']];
+ foreach (['commented', 'received', 'created'] as $orderfields) {
+ if (!empty($parent[$orderfields])) {
+ $activity[$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 = [];
+ }
+ $items = conversation_fetch_items($parent, $items, $condition, $block_authors, $params, $activity);
}
foreach ($items as $index => $item) {
/**
* Fetch conversation items
*
- * @param array $parent
- * @param array $items
- * @param array $condition
- * @param boolean $block_authors
- * @param array $params
+ * @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) {
+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`";
}
- $thread_items = Item::selectForUser(local_user(), array_merge(Item::DISPLAY_FIELDLIST, ['contact-uid', 'gravity', 'post-type']), $condition, $params);
+ $thread_items = Item::selectForUser(local_user(), array_merge(Item::DISPLAY_FIELDLIST, ['pinned', 'contact-uid', 'gravity', 'post-type']), $condition, $params);
- $comments = conversation_fetch_comments($thread_items, $parent['pinned'] ?? false);
+ $comments = conversation_fetch_comments($thread_items, $parent['pinned'] ?? false, $activity);
if (count($comments) != 0) {
$items = array_merge($items, $comments);
DI::l10n()->t('Ignore') => $ignore_link
];
+ if (!empty($item['language'])) {
+ $menu[DI::l10n()->t('Languages')] = 'javascript:alert(\'' . Item::getLanguageMessage($item) . '\');';
+ }
+
if ($network == Protocol::DFRN) {
$menu[DI::l10n()->t("Poke")] = $poke_link;
}
if ((($cid == 0) || ($rel == Contact::FOLLOWER)) &&
in_array($item['network'], Protocol::FEDERATED)) {
- $menu[DI::l10n()->t('Connect/Follow')] = 'follow?url=' . urlencode($item['author-link']);
+ $menu[DI::l10n()->t('Connect/Follow')] = 'follow?url=' . urlencode($item['author-link']) . '&auto=1';
}
} else {
$menu = [DI::l10n()->t('View Profile') => $item['author-link']];
*
* Increments the count of each matching activity and adds a link to the author as needed.
*
- * @param array $item
+ * @param array $activity
* @param array &$conv_responses (already created with builtin activity structure)
* @return void
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
-function builtin_activity_puller($item, &$conv_responses) {
+function builtin_activity_puller(array $activity, array &$conv_responses)
+{
foreach ($conv_responses as $mode => $v) {
$sparkle = '';
return;
}
- if (!empty($item['verb']) && DI::activity()->match($item['verb'], $verb) && ($item['gravity'] != GRAVITY_PARENT)) {
- $author = ['uid' => 0, 'id' => $item['author-id'],
- 'network' => $item['author-network'], 'url' => $item['author-link']];
+ if (!empty($activity['verb']) && DI::activity()->match($activity['verb'], $verb) && ($activity['gravity'] != GRAVITY_PARENT)) {
+ $author = [
+ 'uid' => 0,
+ 'id' => $activity['author-id'],
+ 'network' => $activity['author-network'],
+ 'url' => $activity['author-link']
+ ];
$url = Contact::magicLinkByContact($author);
if (strpos($url, 'redir/') === 0) {
$sparkle = ' class="sparkle" ';
}
- $url = '<a href="'. $url . '"'. $sparkle .'>' . htmlentities($item['author-name']) . '</a>';
+ $link = '<a href="' . $url . '"' . $sparkle . '>' . htmlentities($activity['author-name']) . '</a>';
- if (empty($item['thr-parent'])) {
- $item['thr-parent'] = $item['parent-uri'];
+ if (empty($activity['thr-parent'])) {
+ $activity['thr-parent'] = $activity['parent-uri'];
}
- if (!(isset($conv_responses[$mode][$item['thr-parent'] . '-l'])
- && is_array($conv_responses[$mode][$item['thr-parent'] . '-l']))) {
- $conv_responses[$mode][$item['thr-parent'] . '-l'] = [];
- }
-
- // only list each unique author once
- if (in_array($url,$conv_responses[$mode][$item['thr-parent'] . '-l'])) {
+ // 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'],
+ 'uid' => $activity['uid'], 'causer-id' => $activity['author-id'], 'gravity' => GRAVITY_PARENT])) {
continue;
}
- if (!isset($conv_responses[$mode][$item['thr-parent']])) {
- $conv_responses[$mode][$item['thr-parent']] = 1;
- } else {
- $conv_responses[$mode][$item['thr-parent']] ++;
+ if (!isset($conv_responses[$mode][$activity['thr-parent']])) {
+ $conv_responses[$mode][$activity['thr-parent']] = [
+ 'links' => [],
+ 'self' => 0,
+ ];
+ } elseif (in_array($link, $conv_responses[$mode][$activity['thr-parent']]['links'])) {
+ // only list each unique author once
+ continue;
}
- if (public_contact() == $item['author-id']) {
- $conv_responses[$mode][$item['thr-parent'] . '-self'] = 1;
+ if (public_contact() == $activity['author-id']) {
+ $conv_responses[$mode][$activity['thr-parent']]['self'] = 1;
}
- $conv_responses[$mode][$item['thr-parent'] . '-l'][] = $url;
+ $conv_responses[$mode][$activity['thr-parent']]['links'][] = $link;
// there can only be one activity verb per item so if we found anything, we can stop looking
return;
}
/**
- * Format the vote text for a profile item
+ * Format the activity text for an item/photo/video
*
- * @param int $cnt = number of people who vote the item
- * @param array $arr = array of pre-linked names of likers/dislikers
- * @param string $type = one of 'like, 'dislike', 'attendyes', 'attendno', 'attendmaybe'
- * @param int $id = item id
+ * @param array $links = array of pre-linked names of actors
+ * @param string $verb = one of 'like, 'dislike', 'attendyes', 'attendno', 'attendmaybe'
+ * @param int $id = item id
* @return string formatted text
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
-function format_like($cnt, array $arr, $type, $id) {
+function format_activity(array $links, $verb, $id) {
$o = '';
$expanded = '';
$phrase = '';
- if ($cnt == 1) {
- $likers = $arr[0];
+ $total = count($links);
+ if ($total == 1) {
+ $likers = $links[0];
// Phrase if there is only one liker. In other cases it will be uses for the expanded
// list which show all likers
- switch ($type) {
+ switch ($verb) {
case 'like' :
$phrase = DI::l10n()->t('%s likes this.', $likers);
break;
$phrase = DI::l10n()->t('%s reshared this.', $likers);
break;
}
- }
-
- if ($cnt > 1) {
- $total = count($arr);
+ } elseif ($total > 1) {
if ($total < MAX_LIKERS) {
- $last = DI::l10n()->t('and') . ' ' . $arr[count($arr)-1];
- $arr2 = array_slice($arr, 0, -1);
- $likers = implode(', ', $arr2) . ' ' . $last;
+ $likers = implode(', ', array_slice($links, 0, -1));
+ $likers .= ' ' . DI::l10n()->t('and') . ' ' . $links[count($links)-1];
} else {
- $arr = array_slice($arr, 0, MAX_LIKERS - 1);
- $likers = implode(', ', $arr);
- $likers .= DI::l10n()->t('and %d other people', $total - MAX_LIKERS);
+ $likers = implode(', ', array_slice($links, 0, MAX_LIKERS - 1));
+ $likers .= ' ' . DI::l10n()->t('and %d other people', $total - MAX_LIKERS);
}
- $spanatts = "class=\"fakelink\" onclick=\"openClose('{$type}list-$id');\"";
+ $spanatts = "class=\"fakelink\" onclick=\"openClose('{$verb}list-$id');\"";
$explikers = '';
- switch ($type) {
+ switch ($verb) {
case 'like':
- $phrase = DI::l10n()->t('<span %1$s>%2$d people</span> like this', $spanatts, $cnt);
+ $phrase = DI::l10n()->t('<span %1$s>%2$d people</span> like this', $spanatts, $total);
$explikers = DI::l10n()->t('%s like this.', $likers);
break;
case 'dislike':
- $phrase = DI::l10n()->t('<span %1$s>%2$d people</span> don\'t like this', $spanatts, $cnt);
+ $phrase = DI::l10n()->t('<span %1$s>%2$d people</span> don\'t like this', $spanatts, $total);
$explikers = DI::l10n()->t('%s don\'t like this.', $likers);
break;
case 'attendyes':
- $phrase = DI::l10n()->t('<span %1$s>%2$d people</span> attend', $spanatts, $cnt);
+ $phrase = DI::l10n()->t('<span %1$s>%2$d people</span> attend', $spanatts, $total);
$explikers = DI::l10n()->t('%s attend.', $likers);
break;
case 'attendno':
- $phrase = DI::l10n()->t('<span %1$s>%2$d people</span> don\'t attend', $spanatts, $cnt);
+ $phrase = DI::l10n()->t('<span %1$s>%2$d people</span> don\'t attend', $spanatts, $total);
$explikers = DI::l10n()->t('%s don\'t attend.', $likers);
break;
case 'attendmaybe':
- $phrase = DI::l10n()->t('<span %1$s>%2$d people</span> attend maybe', $spanatts, $cnt);
+ $phrase = DI::l10n()->t('<span %1$s>%2$d people</span> attend maybe', $spanatts, $total);
$explikers = DI::l10n()->t('%s attend maybe.', $likers);
break;
case 'announce':
- $phrase = DI::l10n()->t('<span %1$s>%2$d people</span> reshared this', $spanatts, $cnt);
+ $phrase = DI::l10n()->t('<span %1$s>%2$d people</span> reshared this', $spanatts, $total);
$explikers = DI::l10n()->t('%s reshared this.', $likers);
break;
}
- $expanded .= "\t" . '<p class="wall-item-' . $type . '-expanded" id="' . $type . 'list-' . $id . '" style="display: none;" >' . $explikers . EOL . '</p>';
+ $expanded .= "\t" . '<p class="wall-item-' . $verb . '-expanded" id="' . $verb . 'list-' . $id . '" style="display: none;" >' . $explikers . EOL . '</p>';
}
$o .= Renderer::replaceMacros(Renderer::getMarkupTemplate('voting_fakelink.tpl'), [
'$phrase' => $phrase,
- '$type' => $type,
+ '$type' => $verb,
'$id' => $id
]);
$o .= $expanded;
'$term' => DI::l10n()->t('Tag term:'),
'$fileas' => DI::l10n()->t('Save to Folder:'),
'$whereareu' => DI::l10n()->t('Where are you right now?'),
- '$delitems' => DI::l10n()->t("Delete item\x28s\x29?")
+ '$delitems' => DI::l10n()->t("Delete item\x28s\x29?"),
+ '$is_mobile' => DI::mode()->isMobile(),
]);
$jotplugins = '';
Hook::callAll('jot_tool', $jotplugins);
- // $tpl = Renderer::replaceMacros($tpl,array('$jotplugins' => $jotplugins));
$tpl = Renderer::getMarkupTemplate("jot.tpl");
- $o .= Renderer::replaceMacros($tpl,[
+ $o .= Renderer::replaceMacros($tpl, [
'$new_post' => DI::l10n()->t('New Post'),
'$return_path' => DI::args()->getQueryString(),
'$action' => 'item',