<?php
/**
- * @copyright Copyright (C) 2010-2022, the Friendica project
+ * @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Core\Renderer;
-use Friendica\Core\Session;
use Friendica\DI;
use Friendica\Model\Contact;
use Friendica\Model\Item;
-use Friendica\Model\Photo;
use Friendica\Model\Post as PostModel;
use Friendica\Model\Tag;
use Friendica\Model\User;
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 GuzzleHttp\Psr7\Uri;
use InvalidArgumentException;
/**
$this->setTemplate('wall');
$this->toplevel = $this->getId() == $this->getDataValue('parent');
- if (!empty(Session::getUserIDForVisitorContactID($this->getDataValue('contact-id')))) {
+ if (!empty(DI::userSession()->getUserIDForVisitorContactID($this->getDataValue('contact-id')))) {
$this->visiting = true;
}
$this->writable = $this->getDataValue('writable') || $this->getDataValue('self');
- $author = ['uid' => 0, 'id' => $this->getDataValue('author-id'),
+ $author = [
+ 'uid' => 0,
+ 'id' => $this->getDataValue('author-id'),
'network' => $this->getDataValue('author-network'),
- 'url' => $this->getDataValue('author-link')];
+ 'url' => $this->getDataValue('author-link'),
+ 'alias' => $this->getDataValue('author-alias')
+ ];
$this->redirect_url = Contact::magicLinkByContact($author);
if (!$this->isToplevel()) {
$this->threaded = true;
if (!empty($data['children'])) {
foreach ($data['children'] as $item) {
// Only add will be displayed
- if ($item['network'] === Protocol::MAIL && local_user() != $item['uid']) {
+ if ($item['network'] === Protocol::MAIL && DI::userSession()->getLocalUserId() != $item['uid']) {
continue;
- } elseif (!DI::contentItem()->visibleActivity($item)) {
+ } elseif (!DI::contentItem()->isVisibleActivity($item)) {
continue;
}
// You can always comment on Diaspora and OStatus items
- if (in_array($item['network'], [Protocol::OSTATUS, Protocol::DIASPORA]) && (local_user() == $item['uid'])) {
+ if (in_array($item['network'], [Protocol::OSTATUS, Protocol::DIASPORA]) && (DI::userSession()->getLocalUserId() == $item['uid'])) {
$item['writable'] = true;
}
$pinned = '';
$pin = false;
$star = false;
- $ignore = false;
+ $ignore_thread = false;
$ispinned = 'unpinned';
$isstarred = 'unstarred';
$indent = '';
$lock = ($item['private'] == Item::PRIVATE) ? $privacy : false;
$connector = !in_array($item['network'], Protocol::NATIVE_SUPPORT) ? DI::l10n()->t('Connector Message') : false;
- $shareable = in_array($conv->getProfileOwner(), [0, local_user()]) && $item['private'] != Item::PRIVATE;
- $announceable = $shareable && in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::TWITTER]);
+ $shareable = in_array($conv->getProfileOwner(), [0, DI::userSession()->getLocalUserId()]) && $item['private'] != Item::PRIVATE;
+ $announceable = $shareable && in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::TWITTER, Protocol::TUMBLR, Protocol::BLUESKY]);
+ $commentable = ($item['network'] != Protocol::TUMBLR);
// On Diaspora only toplevel posts can be reshared
- if ($announceable && ($item['network'] == Protocol::DIASPORA) && ($item['gravity'] != GRAVITY_PARENT)) {
+ if ($announceable && ($item['network'] == Protocol::DIASPORA) && ($item['gravity'] != Item::GRAVITY_PARENT)) {
$announceable = false;
}
$edpost = false;
- if (local_user()) {
- if (Strings::compareLink(Session::get('my_url'), $item['author-link'])) {
+ if (DI::userSession()->getLocalUserId()) {
+ if (Strings::compareLink(DI::session()->get('my_url'), $item['author-link'])) {
if ($item['event-id'] != 0) {
- $edpost = ['events/event/' . $item['event-id'], DI::l10n()->t('Edit')];
+ $edpost = ['calendar/event/edit/' . $item['event-id'], DI::l10n()->t('Edit')];
} else {
- $edpost = ['editpost/' . $item['id'], DI::l10n()->t('Edit')];
+ $edpost = [sprintf('post/%s/edit', $item['id']), DI::l10n()->t('Edit')];
}
}
- $dropping = in_array($item['uid'], [0, local_user()]);
+ $dropping = in_array($item['uid'], [0, DI::userSession()->getLocalUserId()]);
}
// Editing on items of not subscribed users isn't currently possible
$edpost = false;
}
- if (($this->getDataValue('uid') == local_user()) || $this->isVisiting()) {
+ if (($this->getDataValue('uid') == DI::userSession()->getLocalUserId()) || $this->isVisiting()) {
$dropping = true;
}
$pinned = DI::l10n()->t('Pinned item');
}
- // Showing the one or the other text, depending upon if we can only hide it or really delete it.
- $delete = $origin ? DI::l10n()->t('Delete globally') : DI::l10n()->t('Remove locally');
-
- $drop = false;
- $block = false;
- if (local_user()) {
+ $drop = false;
+ $block = false;
+ $ignore = false;
+ $collapse = false;
+ $report = false;
+ $ignoreServer = false;
+ if (DI::userSession()->getLocalUserId()) {
$drop = [
'dropping' => $dropping,
'pagedrop' => $item['pagedrop'],
'select' => DI::l10n()->t('Select'),
- 'delete' => $delete,
+ 'label' => $origin ? DI::l10n()->t('Delete globally') : DI::l10n()->t('Remove locally'),
];
}
- if (!$item['self'] && local_user()) {
+ if (!$item['self'] && DI::userSession()->getLocalUserId()) {
$block = [
- 'blocking' => true,
- 'block' => DI::l10n()->t('Block %s', $item['author-name']),
- 'author_id' => $item['author-id'],
+ 'blocking' => true,
+ 'label' => DI::l10n()->t('Block %s', $item['author-name']),
+ 'author_id' => $item['author-id'],
+ ];
+ $ignore = [
+ 'ignoring' => true,
+ 'label' => DI::l10n()->t('Ignore %s', $item['author-name']),
+ 'author_id' => $item['author-id'],
+ ];
+ $collapse = [
+ 'collapsing' => true,
+ 'label' => DI::l10n()->t('Collapse %s', $item['author-name']),
+ 'author_id' => $item['author-id'],
];
+ $report = [
+ 'label' => DI::l10n()->t('Report post'),
+ 'href' => 'moderation/report/create?' . http_build_query(['cid' => $item['author-id'], 'uri-ids' => [$item['uri-id']]]),
+ ];
+ $authorBaseUri = new Uri($item['author-baseurl'] ?? '');
+ if ($authorBaseUri->getHost() && !DI::baseUrl()->isLocalUrl($authorBaseUri)) {
+ $ignoreServer = [
+ 'label' => DI::l10n()->t("Ignore %s server", $authorBaseUri->getHost()),
+ ];
+ }
}
- $filer = local_user() ? DI::l10n()->t('Save to folder') : false;
+ $filer = DI::userSession()->getLocalUserId() ? DI::l10n()->t('Save to folder') : false;
$profile_name = $item['author-name'];
if (!empty($item['author-link']) && empty($item['author-name'])) {
$profile_name = $item['author-link'];
}
- if (Session::isAuthenticated()) {
- $author = ['uid' => 0, 'id' => $item['author-id'],
- 'network' => $item['author-network'], 'url' => $item['author-link']];
+ if (DI::userSession()->isAuthenticated()) {
+ $author = [
+ 'uid' => 0,
+ 'id' => $item['author-id'],
+ 'network' => $item['author-network'],
+ 'url' => $item['author-link'],
+ 'alias' => $item['author-alias'],
+ ];
$profile_link = Contact::magicLinkByContact($author);
} else {
$profile_link = $item['author-link'];
}
- if (strpos($profile_link, 'redir/') === 0) {
+ if (strpos($profile_link, 'contact/redir/') === 0) {
$sparkle = ' sparkle';
}
$tagger = '';
if ($this->isToplevel()) {
- if (local_user()) {
- $ignored = PostModel\ThreadUser::getIgnored($item['uri-id'], local_user());
- if ($item['mention'] || $ignored) {
- $ignore = [
+ if (DI::userSession()->getLocalUserId()) {
+ $ignored_thread = PostModel\ThreadUser::getIgnored($item['uri-id'], DI::userSession()->getLocalUserId());
+ if ($item['mention'] || $ignored_thread) {
+ $ignore_thread = [
'do' => DI::l10n()->t('Ignore thread'),
'undo' => DI::l10n()->t('Unignore thread'),
'toggle' => DI::l10n()->t('Toggle ignore status'),
- 'classdo' => $ignored ? 'hidden' : '',
- 'classundo' => $ignored ? '' : 'hidden',
+ 'classdo' => $ignored_thread ? 'hidden' : '',
+ 'classundo' => $ignored_thread ? '' : 'hidden',
'ignored' => DI::l10n()->t('Ignored'),
];
}
'starred' => DI::l10n()->t('Starred'),
];
- if ($conv->getProfileOwner() == local_user() && ($item['uid'] != 0)) {
+ if ($conv->getProfileOwner() == DI::userSession()->getLocalUserId() && ($item['uid'] != 0)) {
if ($origin && in_array($item['private'], [Item::PUBLIC, Item::UNLISTED])) {
$ispinned = ($item['featured'] ? 'pinned' : 'unpinned');
}
if ($conv->isWritable()) {
- $buttons['like'] = [DI::l10n()->t("I like this \x28toggle\x29") , DI::l10n()->t('Like')];
+ $buttons['like'] = [DI::l10n()->t("I like this \x28toggle\x29"), DI::l10n()->t('Like')];
$buttons['dislike'] = [DI::l10n()->t("I don't like this \x28toggle\x29"), DI::l10n()->t('Dislike')];
if ($shareable) {
$buttons['share'] = [DI::l10n()->t('Quote share this'), DI::l10n()->t('Quote Share')];
}
}
- $comment_html = $this->getCommentBox($indent);
+ if ($commentable) {
+ $comment_html = $this->getCommentBox($indent);
+ } else {
+ $comment_html = '';
+ }
if (strcmp(DateTimeFormat::utc($item['created']), DateTimeFormat::utc('now - 12 hours')) > 0) {
$shiny = 'shiny';
$body_html = Item::prepareBody($item, true);
- list($categories, $folders) = DI::contentItem()->determineCategoriesTerms($item, local_user());
+ list($categories, $folders) = DI::contentItem()->determineCategoriesTerms($item, DI::userSession()->getLocalUserId());
if (!empty($item['title'])) {
$title = $item['title'];
- } elseif (!empty($item['content-warning']) && DI::pConfig()->get(local_user(), 'system', 'disable_cw', false)) {
+ } elseif (!empty($item['content-warning']) && DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'disable_cw', false)) {
$title = ucfirst($item['content-warning']);
} else {
$title = '';
}
- if (DI::pConfig()->get(local_user(), 'system', 'hide_dislike')) {
+ if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'hide_dislike')) {
$buttons['dislike'] = false;
}
}
// Fetching of Diaspora posts doesn't always work. There are issues with reshares and possibly comments
- if (!local_user() && ($item['network'] != Protocol::DIASPORA) && !empty(Session::get('remote_comment'))) {
- $remote_comment = [DI::l10n()->t('Comment this item on your system'), DI::l10n()->t('Remote comment'),
- str_replace('{uri}', urlencode($item['uri']), Session::get('remote_comment'))];
+ if (!DI::userSession()->getLocalUserId() && ($item['network'] != Protocol::DIASPORA) && !empty(DI::session()->get('remote_comment'))) {
+ $remote_comment = [
+ DI::l10n()->t('Comment this item on your system'), DI::l10n()->t('Remote comment'),
+ str_replace('{uri}', urlencode($item['uri']), DI::session()->get('remote_comment'))
+ ];
// Ensure to either display the remote comment or the local activities
$buttons = [];
'location_html' => $location_html,
'indent' => $indent,
'shiny' => $shiny,
- 'owner_self' => $item['author-link'] == Session::get('my_url'),
+ 'owner_self' => $item['author-link'] == DI::session()->get('my_url'),
'owner_url' => $this->getOwnerUrl(),
'owner_photo' => DI::baseUrl()->remove(DI::contentItem()->getOwnerAvatar($item)),
'owner_name' => $this->getOwnerName(),
'pinned' => $pinned,
'isstarred' => $isstarred,
'star' => $star,
- 'ignore' => $ignore,
+ 'ignore' => $ignore_thread,
'tagger' => $tagger,
'filer' => $filer,
'language' => $languages,
'drop' => $drop,
'block' => $block,
+ 'ignore_author' => $ignore,
+ 'collapse' => $collapse,
+ 'report' => $report,
+ 'ignore_server' => $ignoreServer,
'vote' => $buttons,
'like_html' => $responses['like']['output'],
'dislike_html' => $responses['dislike']['output'],
+ 'emojis' => $this->getEmojis($item),
'responses' => $responses,
'switchcomment' => DI::l10n()->t('Comment'),
'reply_label' => DI::l10n()->t('Reply to %s', $profile_name),
'wait' => DI::l10n()->t('Please wait'),
'thread_level' => $thread_level,
'edited' => $edited,
+ 'author_gsid' => $item['author-gsid'],
'network' => $item['network'],
'network_name' => ContactSelector::networkToName($item['author-network'], $item['author-link'], $item['network'], $item['author-gsid']),
'network_icon' => ContactSelector::networkToIcon($item['network'], $item['author-link'], $item['author-gsid']),
}
}
+ // Copy values/set defaults
$result['total_comments_num'] = $this->isToplevel() ? $total_children : 0;
+ $result['private'] = $item['private'];
+ $result['toplevel'] = ($this->isToplevel() ? 'toplevel_item' : '');
+ $result['flatten'] = !$this->isThreaded();
+ $result['threaded'] = $this->isThreaded();
- $result['private'] = $item['private'];
- $result['toplevel'] = ($this->isToplevel() ? 'toplevel_item' : '');
+ return $result;
+ }
- if ($this->isThreaded()) {
- $result['flatten'] = false;
- $result['threaded'] = true;
- } else {
- $result['flatten'] = true;
- $result['threaded'] = false;
+ /**
+ * Fetch emojis
+ *
+ * @param array $item
+ * @return array
+ */
+ private function getEmojis(array $item): array
+ {
+ if (empty($item['emojis'])) {
+ return [];
}
- return $result;
+ $emojis = [];
+ foreach ($item['emojis'] as $index => $element) {
+ $actors = implode(', ', $element['title']);
+ switch ($element['verb']) {
+ case Activity::ANNOUNCE:
+ $title = DI::l10n()->t('Reshared by: %s', $actors);
+ $icon = ['fa' => 'fa-retweet', 'icon' => 'icon-retweet'];
+ break;
+
+ case Activity::VIEW:
+ $title = DI::l10n()->t('Viewed by: %s', $actors);
+ $icon = ['fa' => 'fa-eye', 'icon' => 'icon-eye-open'];
+ break;
+
+ case Activity::LIKE:
+ $title = DI::l10n()->t('Liked by: %s', $actors);
+ $icon = ['fa' => 'fa-thumbs-up', 'icon' => 'icon-thumbs-up'];
+ break;
+
+ case Activity::DISLIKE:
+ $title = DI::l10n()->t('Disliked by: %s', $actors);
+ $icon = ['fa' => 'fa-thumbs-down', 'icon' => 'icon-thumbs-down'];
+ break;
+
+ case Activity::ATTEND:
+ $title = DI::l10n()->t('Attended by: %s', $actors);
+ $icon = ['fa' => 'fa-check', 'icon' => 'icon-ok'];
+ break;
+
+ case Activity::ATTENDMAYBE:
+ $title = DI::l10n()->t('Maybe attended by: %s', $actors);
+ $icon = ['fa' => 'fa-question', 'icon' => 'icon-question'];
+ break;
+
+ case Activity::ATTENDNO:
+ $title = DI::l10n()->t('Not attended by: %s', $actors);
+ $icon = ['fa' => 'fa-times', 'icon' => 'icon-remove'];
+ break;
+
+ default:
+ $title = DI::l10n()->t('Reacted with %s by: %s', $element['emoji'], $actors);
+ $icon = [];
+ break;
+ }
+ $emojis[$index] = ['emoji' => $element['emoji'], 'total' => $element['total'], 'title' => $title, 'icon' => $icon];
+ }
+ ksort($emojis);
+
+ return $emojis;
}
/**
}
/**
- * Add a child item
+ * Add a child post
*
- * @param Post $item The child item to add
+ * @param Post $item The child post to add
*
- * @return mixed
+ * @return Post|bool Last Post object or bool on any error
* @throws \Exception
*/
public function addChild(Post $item)
{
- $item_id = $item->getId();
- if (!$item_id) {
- Logger::info('[ERROR] Post::addChild : Item has no ID!!');
+ if (!$item->getId()) {
+ Logger::error('Post object has no id', ['post' => $item]);
return false;
} elseif ($this->getChild($item->getId())) {
- Logger::info('[WARN] Post::addChild : Item already exists (' . $item->getId() . ').');
+ Logger::warning('Post object already exists', ['post' => $item]);
return false;
}
- $activity = DI::activity();
-
/*
* Only add what will be displayed
*/
- if ($item->getDataValue('network') === Protocol::MAIL && local_user() != $item->getDataValue('uid')) {
+ if ($item->getDataValue('network') === Protocol::MAIL && DI::userSession()->getLocalUserId() != $item->getDataValue('uid')) {
+ Logger::warning('Post object does not belong to local user', ['post' => $item, 'local_user' => DI::userSession()->getLocalUserId()]);
return false;
- } elseif ($activity->match($item->getDataValue('verb'), Activity::LIKE) ||
- $activity->match($item->getDataValue('verb'), Activity::DISLIKE)) {
+ } elseif (
+ DI::activity()->match($item->getDataValue('verb'), Activity::LIKE) ||
+ DI::activity()->match($item->getDataValue('verb'), Activity::DISLIKE)
+ ) {
+ Logger::warning('Post objects is a like/dislike', ['post' => $item]);
return false;
}
* Get a child by its ID
*
* @param integer $id The child id
- * @return mixed
+ * @return Thread|null Thread or NULL if not found
*/
public function getChild(int $id)
{
/**
* Set conversation thread
*
- * @param Thread $thread Thread to set or NULL
+ * @param Thread|null $thread
+ *
* @return void
*/
public function setThread(Thread $thread = null)
/**
* Get conversation
*
- * @return Thread
+ * @return Thread|null
*/
public function getThread()
{
* Get a data value
*
* @param string $name key
+ *
* @return mixed value on success, false on failure
*/
public function getDataValue(string $name)
}
/**
- * Set template
+ * Set template by name
*
* @param string $name Template name
- * @return bool If template was set
+ *
+ * @return void
* @throws InvalidArgumentException
*/
- private function setTemplate(string $name): bool
+ private function setTemplate(string $name)
{
if (empty($this->available_templates[$name])) {
// Throw exception
}
$this->template = $this->available_templates[$name];
-
- return true;
}
/**
if ($conv) {
// This will allow us to comment on wall-to-wall items owned by our friends
- // and community forums even if somebody else wrote the post.
+ // and community groups even if somebody else wrote the post.
// bug #517 - this fixes for conversation owner
- if ($conv->getMode() == 'profile' && $conv->getProfileOwner() == local_user()) {
+ if ($conv->getMode() == 'profile' && $conv->getProfileOwner() == DI::userSession()->getLocalUserId()) {
return true;
}
{
$a = DI::app();
- if (!local_user()) {
+ if (!DI::userSession()->getLocalUserId()) {
return '';
}
$owner = User::getOwnerDataById($a->getLoggedInUserId());
$item = $this->getData();
- if (!empty($item['content-warning']) && Feature::isEnabled(local_user(), 'add_abstract')) {
+ if (!empty($item['content-warning']) && Feature::isEnabled(DI::userSession()->getLocalUserId(), 'add_abstract')) {
$text = '[abstract=' . Protocol::ACTIVITYPUB . ']' . $item['content-warning'] . "[/abstract]\n";
} else {
$text = '';
}
- if (!Feature::isEnabled(local_user(), 'explicit_mentions')) {
+ if (!Feature::isEnabled(DI::userSession()->getLocalUserId(), 'explicit_mentions')) {
return $text;
}
- if (($item['author-addr'] != $owner['addr']) && (($item['gravity'] != GRAVITY_PARENT) || !in_array($item['network'], [Protocol::DIASPORA]))) {
+ if (($item['author-addr'] != $owner['addr']) && (($item['gravity'] != Item::GRAVITY_PARENT) || !in_array($item['network'], [Protocol::DIASPORA]))) {
$text .= '@' . $item['author-addr'] . ' ';
}
}
$profile = Contact::getByURL($term['url'], false, ['addr', 'contact-type']);
- if (!empty($profile['addr']) && (($profile['contact-type'] ?? Contact::TYPE_UNKNOWN) != Contact::TYPE_COMMUNITY) &&
- ($profile['addr'] != $owner['addr']) && !strstr($text, $profile['addr'])) {
+ if (
+ !empty($profile['addr']) && (($profile['contact-type'] ?? Contact::TYPE_UNKNOWN) != Contact::TYPE_COMMUNITY) &&
+ ($profile['addr'] != $owner['addr']) && !strstr($text, $profile['addr'])
+ ) {
$text .= '@' . $profile['addr'] . ' ';
}
}
* Get the comment box
*
* @param string $indent Indent value
+ *
* @return mixed The comment box string (empty if no comment box), false on failure
* @throws \Exception
* @todo return false is nowhere in this method?
*/
$qcomment = null;
if (Addon::isEnabled('qcomment')) {
- $words = DI::pConfig()->get(local_user(), 'qcomment', 'words');
+ $words = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'qcomment', 'words');
$qcomment = $words ? explode("\n", $words) : [];
}
'$edbold' => DI::l10n()->t('Bold'),
'$editalic' => DI::l10n()->t('Italic'),
'$eduline' => DI::l10n()->t('Underline'),
+ '$contentwarn' => DI::l10n()->t('Content Warning'),
'$edquote' => DI::l10n()->t('Quote'),
+ '$edemojis' => DI::l10n()->t('Add emojis'),
'$edcode' => DI::l10n()->t('Code'),
'$edimg' => DI::l10n()->t('Image'),
'$edurl' => DI::l10n()->t('Link'),
$this->wall_to_wall = true;
$owner = [
- 'uid' => 0,
- 'id' => $this->getDataValue('owner-id'),
+ 'uid' => 0,
+ 'id' => $this->getDataValue('owner-id'),
'network' => $this->getDataValue('owner-network'),
- 'url' => $this->getDataValue('owner-link'),
+ 'url' => $this->getDataValue('owner-link'),
+ 'alias' => $this->getDataValue('owner-alias'),
];
$this->owner_url = Contact::magicLinkByContact($owner);
}