X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=src%2FContent%2FConversation.php;h=458a0a690f19fe97ed5a481723cc4d9b2340e0fd;hb=ae2e8beaaca342a0d5ced45beb0fc6c1b4f8a4a4;hp=c5e854b1d9ece6a02f55ab98e9238aec0ef4022b;hpb=91ff24b0e4cb4b01f0af2a457bdf66945090ffb0;p=friendica.git diff --git a/src/Content/Conversation.php b/src/Content/Conversation.php index c5e854b1d9..458a0a690f 100644 --- a/src/Content/Conversation.php +++ b/src/Content/Conversation.php @@ -41,6 +41,7 @@ use Friendica\Model\Post; use Friendica\Model\Tag; use Friendica\Model\User; use Friendica\Model\Verb; +use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Object\Post as PostObject; use Friendica\Object\Thread; use Friendica\Protocol\Activity; @@ -193,6 +194,52 @@ class Conversation } } + /** + * Returns the liker phrase based on a list of likers + * + * @param string $verb the activity verb + * @param array $likers a list of likers + * + * @return string the liker phrase + * + * @throws InternalServerErrorException in case either the verb is invalid or the list of likers is empty + */ + private function getLikerPhrase(string $verb, array $likers): string + { + $total = count($likers); + + if ($total === 0) { + throw new InternalServerErrorException(sprintf('There has to be at least one Liker for verb "%s"', $verb)); + } else if ($total === 1) { + $likerString = $likers[0]; + } else { + if ($total < $this->config->get('system', 'max_likers')) { + $likerString = implode(', ', array_slice($likers, 0, -1)); + $likerString .= ' ' . $this->l10n->t('and') . ' ' . $likers[count($likers) - 1]; + } else { + $likerString = implode(', ', array_slice($likers, 0, $this->config->get('system', 'max_likers') - 1)); + $likerString .= ' ' . $this->l10n->t('and %d other people', $total - $this->config->get('system', 'max_likers')); + } + } + + switch ($verb) { + case 'like': + return $this->l10n->tt('%2$s likes this.', '%2$s like this.', $total, $likerString); + case 'dislike': + return $this->l10n->tt('%2$s doesn\'t like this.', '%2$s don\'t like this.', $total, $likerString); + case 'attendyes': + return $this->l10n->tt('%2$s attends.', '%2$s attend.', $total, $likerString); + case 'attendno': + return $this->l10n->tt('%2$s doesn\'t attend.', '%2$s don\'t attend.', $total, $likerString); + case 'attendmaybe': + return $this->l10n->tt('%2$s attends maybe.', '%2$s attend maybe.', $total, $likerString); + case 'announce': + return $this->l10n->tt('%2$s reshared this.', '%2$s reshared this.', $total, $likerString); + default: + throw new InternalServerErrorException(sprintf('Unknown verb "%s"', $verb)); + } + } + /** * Format the activity text for an item/photo/video * @@ -205,87 +252,48 @@ class Conversation public function formatActivity(array $links, string $verb, int $id): string { $this->profiler->startRecording('rendering'); - $o = ''; $expanded = ''; - $phrase = ''; - $total = count($links); - if ($total == 1) { - $likers = $links[0]; + $phrase = $this->getLikerPhrase($verb, $links); + $total = count($links); - // Phrase if there is only one liker. In other cases it will be uses for the expanded - // list which show all likers - switch ($verb) { - case 'like': - $phrase = $this->l10n->t('%s likes this.', $likers); - break; - case 'dislike': - $phrase = $this->l10n->t('%s doesn\'t like this.', $likers); - break; - case 'attendyes': - $phrase = $this->l10n->t('%s attends.', $likers); - break; - case 'attendno': - $phrase = $this->l10n->t('%s doesn\'t attend.', $likers); - break; - case 'attendmaybe': - $phrase = $this->l10n->t('%s attends maybe.', $likers); - break; - case 'announce': - $phrase = $this->l10n->t('%s reshared this.', $likers); - break; - } - } elseif ($total > 1) { - if ($total < $this->config->get('system', 'max_likers')) { - $likers = implode(', ', array_slice($links, 0, -1)); - $likers .= ' ' . $this->l10n->t('and') . ' ' . $links[count($links) - 1]; - } else { - $likers = implode(', ', array_slice($links, 0, $this->config->get('system', 'max_likers') - 1)); - $likers .= ' ' . $this->l10n->t('and %d other people', $total - $this->config->get('system', 'max_likers')); - } + if ($total > 1) { + $spanatts = "class=\"btn btn-link fakelink\" onclick=\"openClose('{$verb}list-$id');\""; + $explikers = $phrase; - $spanatts = "class=\"btn btn-link fakelink\" onclick=\"openClose('{$verb}list-$id');\""; - - $explikers = ''; switch ($verb) { case 'like': - $phrase = $this->l10n->t(' like this', $spanatts, $total); - $explikers = $this->l10n->t('%s like this.', $likers); + $phrase = $this->l10n->tt(' likes this', ' like this', $total, $spanatts); break; case 'dislike': - $phrase = $this->l10n->t(' don\'t like this', $spanatts, $total); - $explikers = $this->l10n->t('%s don\'t like this.', $likers); + $phrase = $this->l10n->tt(' doesn\'t like this', ' don\'t like this', $total, $spanatts); break; case 'attendyes': - $phrase = $this->l10n->t(' attend', $spanatts, $total); - $explikers = $this->l10n->t('%s attend.', $likers); + $phrase = $this->l10n->tt(' attends', ' attend', $total, $spanatts); break; case 'attendno': - $phrase = $this->l10n->t(' don\'t attend', $spanatts, $total); - $explikers = $this->l10n->t('%s don\'t attend.', $likers); + $phrase = $this->l10n->tt(' doesn\'t attend',' don\'t attend', $total, $spanatts); break; case 'attendmaybe': - $phrase = $this->l10n->t(' attend maybe', $spanatts, $total); - $explikers = $this->l10n->t('%s attend maybe.', $likers); + $phrase = $this->l10n->tt(' attends maybe', ' attend maybe', $total, $spanatts); break; case 'announce': - $phrase = $this->l10n->t(' reshared this', $spanatts, $total); - $explikers = $this->l10n->t('%s reshared this.', $likers); + $phrase = $this->l10n->tt(' reshared this', ' reshared this', $total, $spanatts); break; } $expanded .= "\t" . ''; } - $o .= Renderer::replaceMacros(Renderer::getMarkupTemplate('voting_fakelink.tpl'), [ + $output = Renderer::replaceMacros(Renderer::getMarkupTemplate('voting_fakelink.tpl'), [ '$phrase' => $phrase, '$type' => $verb, '$id' => $id ]); - $o .= $expanded; + $output .= $expanded; $this->profiler->stopRecording(); - return $o; + return $output; } public function statusEditor(array $x = [], int $notes_cid = 0, bool $popup = false): string @@ -314,7 +322,7 @@ class Conversation $tpl = Renderer::getMarkupTemplate('jot-header.tpl'); $this->page['htmlhead'] .= Renderer::replaceMacros($tpl, [ '$newpost' => 'true', - '$baseurl' => $this->baseURL->get(true), + '$baseurl' => $this->baseURL, '$geotag' => $geotag, '$nickname' => $x['nickname'], '$ispublic' => $this->l10n->t('Visible to everybody'), @@ -385,7 +393,7 @@ class Conversation '$posttype' => $notes_cid ? ItemModel::PT_PERSONAL_NOTE : ItemModel::PT_ARTICLE, '$content' => $x['content'] ?? '', '$post_id' => $x['post_id'] ?? '', - '$baseurl' => $this->baseURL->get(true), + '$baseurl' => $this->baseURL, '$defloc' => $x['default_location'], '$visitor' => $x['visitor'], '$pvisit' => $notes_cid ? 'none' : $x['visitor'], @@ -446,8 +454,6 @@ class Conversation $this->page->registerStylesheet(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput.css')); $this->page->registerStylesheet(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput-typeahead.css')); - $ssl_state = (bool)$this->session->getLocalUserId(); - $live_update_div = ''; $blocklist = $this->getBlocklist(); @@ -784,7 +790,7 @@ class Conversation } $o = Renderer::replaceMacros($page_template, [ - '$baseurl' => $this->baseURL->get($ssl_state), + '$baseurl' => $this->baseURL, '$return_path' => $this->args->getQueryString(), '$live_update' => $live_update_div, '$remove' => $this->l10n->t('remove'), @@ -979,9 +985,16 @@ class Conversation $condition['author-hidden'] = false; } + if ($this->config->get('system', 'emoji_activities')) { + $emojis = $this->getEmojis($uriids); + $condition = DBA::mergeConditions($condition, ["(`gravity` != ? OR `origin`)", ItemModel::GRAVITY_ACTIVITY]); + } + $condition = DBA::mergeConditions($condition, ["`uid` IN (0, ?) AND (NOT `vid` IN (?, ?, ?) OR `vid` IS NULL)", $uid, Verb::getID(Activity::FOLLOW), Verb::getID(Activity::VIEW), Verb::getID(Activity::READ)]); + $condition = DBA::mergeConditions($condition, ["(`uid` != ? OR `private` != ?)", 0, ItemModel::PRIVATE]); + $condition = DBA::mergeConditions($condition, ["`visible` AND NOT `deleted` AND NOT `author-blocked` AND NOT `owner-blocked` AND ((NOT `contact-pending` AND (`contact-rel` IN (?, ?))) OR `self` OR `contact-uid` = ?)", @@ -1081,6 +1094,8 @@ class Conversation } foreach ($items as $key => $row) { + $items[$key]['emojis'] = $emojis[$key] ?? []; + $always_display = in_array($mode, [self::MODE_CONTACTS, self::MODE_CONTACT_POSTS]); $items[$key]['user-blocked-author'] = !$always_display && in_array($row['author-id'], $blocks); @@ -1102,6 +1117,53 @@ class Conversation return $items; } + /** + * Fetch emoji reaction from the conversation + * + * @param array $uriids + * @return array + */ + private function getEmojis(array $uriids): array + { + $activity_emoji = [ + Activity::LIKE => '👍', + Activity::DISLIKE => '👎', + Activity::ATTEND => '✔️', + Activity::ATTENDMAYBE => '❓', + Activity::ATTENDNO => '❌', + Activity::ANNOUNCE => '♻', + Activity::VIEW => '📺', + ]; + + $index_list = array_values($activity_emoji); + $verbs = array_merge(array_keys($activity_emoji), [Activity::EMOJIREACT]); + + $condition = DBA::mergeConditions(['parent-uri-id' => $uriids, 'gravity' => ItemModel::GRAVITY_ACTIVITY, 'verb' => $verbs], ["NOT `deleted`"]); + $separator = chr(255) . chr(255) . chr(255); + + $sql = "SELECT `thr-parent-id`, `body`, `verb`, COUNT(*) AS `total`, GROUP_CONCAT(REPLACE(`author-name`, '" . $separator . "', ' ') SEPARATOR '". $separator ."' LIMIT 50) AS `title` FROM `post-view` WHERE " . array_shift($condition) . " GROUP BY `thr-parent-id`, `verb`, `body`"; + + $emojis = []; + + $rows = DBA::p($sql, $condition); + while ($row = DBA::fetch($rows)) { + $row['verb'] = $row['body'] ? Activity::EMOJIREACT : $row['verb']; + $emoji = $row['body'] ?: $activity_emoji[$row['verb']]; + if (!isset($index_list[$emoji])) { + $index_list[] = $emoji; + } + $index = array_search($emoji, $index_list); + + $emojis[$row['thr-parent-id']][$index]['emoji'] = $emoji; + $emojis[$row['thr-parent-id']][$index]['verb'] = $row['verb']; + $emojis[$row['thr-parent-id']][$index]['total'] = ($emojis[$row['thr-parent-id']][$index]['total'] ?? 0) + $row['total']; + $emojis[$row['thr-parent-id']][$index]['title'] = array_unique(array_merge($emojis[$row['thr-parent-id']][$index]['title'] ?? [], explode($separator, $row['title']))); + } + DBA::close($rows); + + return $emojis; + } + /** * Plucks the children of the given parent from a given item list. * @@ -1308,7 +1370,7 @@ class Conversation } } - /// @TODO: Stop recusrsively adding all children back to the top level (!!!) + /// @TODO: Stop recursively adding all children back to the top level (!!!) /// However, this apparently ensures responses (likes, attendance) display (?!) foreach ($parents as $parent) { if (count($parent['children'])) {