Display featured posts for contacts
This commit is contained in:
@@ -639,6 +639,12 @@ class Conversation
|
||||
$title = '';
|
||||
}
|
||||
|
||||
if (!empty($item['featured'])) {
|
||||
$pinned = $this->l10n->t('Pinned item');
|
||||
} else {
|
||||
$pinned = '';
|
||||
}
|
||||
|
||||
$tmp_item = [
|
||||
'template' => $tpl,
|
||||
'id' => ($preview ? 'P0' : $item['id']),
|
||||
@@ -680,6 +686,7 @@ class Conversation
|
||||
'owner_photo' => $this->baseURL->remove(Contact::getAvatarUrlForUrl($item['owner-link'], $item['uid'], Proxy::SIZE_THUMB)),
|
||||
'plink' => ItemModel::getPlink($item),
|
||||
'edpost' => false,
|
||||
'pinned' => $pinned,
|
||||
'isstarred' => 'unstarred',
|
||||
'star' => false,
|
||||
'drop' => $drop,
|
||||
@@ -931,7 +938,7 @@ class Conversation
|
||||
$condition = DBA::mergeConditions($condition,
|
||||
["`uid` IN (0, ?) AND (`vid` != ? OR `vid` IS NULL)", $uid, Verb::getID(Activity::FOLLOW)]);
|
||||
|
||||
$thread_items = Post::selectForUser($uid, array_merge(ItemModel::DISPLAY_FIELDLIST, ['pinned', 'contact-uid', 'gravity', 'post-type', 'post-reason']), $condition, $params);
|
||||
$thread_items = Post::selectForUser($uid, array_merge(ItemModel::DISPLAY_FIELDLIST, ['featured', 'contact-uid', 'gravity', 'post-type', 'post-reason']), $condition, $params);
|
||||
|
||||
$items = [];
|
||||
|
||||
@@ -1135,7 +1142,9 @@ class Conversation
|
||||
}
|
||||
|
||||
if (stristr($order, 'pinned_received')) {
|
||||
usort($parents, [$this, 'sortThrPinnedReceived']);
|
||||
usort($parents, [$this, 'sortThrFeaturedReceived']);
|
||||
} elseif (stristr($order, 'pinned_commented')) {
|
||||
usort($parents, [$this, 'sortThrFeaturedCommented']);
|
||||
} elseif (stristr($order, 'received')) {
|
||||
usort($parents, [$this, 'sortThrReceived']);
|
||||
} elseif (stristr($order, 'commented')) {
|
||||
@@ -1174,23 +1183,41 @@ class Conversation
|
||||
}
|
||||
|
||||
/**
|
||||
* usort() callback to sort item arrays by pinned and the received key
|
||||
* usort() callback to sort item arrays by featured and the received key
|
||||
*
|
||||
* @param array $a
|
||||
* @param array $b
|
||||
* @return int
|
||||
*/
|
||||
private function sortThrPinnedReceived(array $a, array $b)
|
||||
private function sortThrFeaturedReceived(array $a, array $b)
|
||||
{
|
||||
if ($b['pinned'] && !$a['pinned']) {
|
||||
if ($b['featured'] && !$a['featured']) {
|
||||
return 1;
|
||||
} elseif (!$b['pinned'] && $a['pinned']) {
|
||||
} elseif (!$b['featured'] && $a['featured']) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return strcmp($b['received'], $a['received']);
|
||||
}
|
||||
|
||||
/**
|
||||
* usort() callback to sort item arrays by featured and the received key
|
||||
*
|
||||
* @param array $a
|
||||
* @param array $b
|
||||
* @return int
|
||||
*/
|
||||
private function sortThrFeaturedCommented(array $a, array $b)
|
||||
{
|
||||
if ($b['featured'] && !$a['featured']) {
|
||||
return 1;
|
||||
} elseif (!$b['featured'] && $a['featured']) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return strcmp($b['commented'], $a['commented']);
|
||||
}
|
||||
|
||||
/**
|
||||
* usort() callback to sort item arrays by the received key
|
||||
*
|
||||
|
||||
@@ -78,7 +78,7 @@ class Status extends BaseFactory
|
||||
public function createFromUriId(int $uriId, $uid = 0): \Friendica\Object\Api\Mastodon\Status
|
||||
{
|
||||
$fields = ['uri-id', 'uid', 'author-id', 'author-link', 'starred', 'app', 'title', 'body', 'raw-body', 'content-warning',
|
||||
'created', 'network', 'thr-parent-id', 'parent-author-id', 'language', 'uri', 'plink', 'private', 'vid', 'gravity'];
|
||||
'created', 'network', 'thr-parent-id', 'parent-author-id', 'language', 'uri', 'plink', 'private', 'vid', 'gravity', 'featured'];
|
||||
$item = Post::selectFirst($fields, ['uri-id' => $uriId, 'uid' => [0, $uid]], ['order' => ['uid' => true]]);
|
||||
if (!$item) {
|
||||
$mail = DBA::selectFirst('mail', ['id'], ['uri-id' => $uriId, 'uid' => $uid]);
|
||||
@@ -125,7 +125,7 @@ class Status extends BaseFactory
|
||||
]),
|
||||
Post\ThreadUser::getIgnored($uriId, $uid),
|
||||
(bool)($item['starred'] && ($item['gravity'] == GRAVITY_PARENT)),
|
||||
Post\ThreadUser::getPinned($uriId, $uid)
|
||||
$item['featured']
|
||||
);
|
||||
|
||||
$sensitive = $this->dba->exists('tag-view', ['uri-id' => $uriId, 'name' => 'nsfw', 'type' => TagModel::HASHTAG]);
|
||||
|
||||
+23
-3
@@ -38,6 +38,7 @@ use Friendica\DI;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Network\Probe;
|
||||
use Friendica\Protocol\Activity;
|
||||
use Friendica\Protocol\ActivityPub;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Images;
|
||||
use Friendica\Util\Network;
|
||||
@@ -1455,11 +1456,26 @@ class Contact
|
||||
}
|
||||
|
||||
if ($thread_mode) {
|
||||
$items = Post::toArray(Post::selectForUser(local_user(), ['uri-id', 'gravity', 'parent-uri-id', 'thr-parent-id', 'author-id'], $condition, $params));
|
||||
$items = Post::toArray(Post::selectForUser(local_user(), ['uri-id'], $condition, $params));
|
||||
|
||||
$o .= DI::conversation()->create($items, 'contacts', $update, false, 'commented', local_user());
|
||||
if ($pager->getStart() == 0) {
|
||||
$cdata = Contact::getPublicAndUserContactID($cid, local_user());
|
||||
$pinned = DBA::selectToArray('collection-view', ['uri-id'], ['cid' => $cdata['public']]);
|
||||
$items = array_merge($items, $pinned);
|
||||
}
|
||||
|
||||
$o .= DI::conversation()->create($items, 'contacts', $update, false, 'pinned_commented', local_user());
|
||||
} else {
|
||||
$items = Post::toArray(Post::selectForUser(local_user(), Item::DISPLAY_FIELDLIST, $condition, $params));
|
||||
$fields = array_merge(Item::DISPLAY_FIELDLIST, ['featured']);
|
||||
$items = Post::toArray(Post::selectForUser(local_user(), $fields, $condition, $params));
|
||||
|
||||
if ($pager->getStart() == 0) {
|
||||
$cdata = Contact::getPublicAndUserContactID($cid, local_user());
|
||||
$condition = ["`uri-id` IN (SELECT `uri-id` FROM `collection-view` WHERE `cid` = ?)", $cdata['public']];
|
||||
$pinned = Post::toArray(Post::selectForUser(local_user(), $fields, $condition, $params));
|
||||
//$items = $pinned;
|
||||
$items = array_merge($pinned, $items);
|
||||
}
|
||||
|
||||
$o .= DI::conversation()->create($items, 'contact-posts', $update);
|
||||
}
|
||||
@@ -2252,6 +2268,10 @@ class Contact
|
||||
$new_pubkey = $ret['pubkey'] ?? '';
|
||||
|
||||
if ($uid == 0) {
|
||||
if ($ret['network'] == Protocol::ACTIVITYPUB) {
|
||||
ActivityPub\Processor::fetchFeaturedPosts($ret['url']);
|
||||
}
|
||||
|
||||
$ret['last-item'] = Probe::getLastUpdate($ret);
|
||||
Logger::info('Fetched last item', ['id' => $id, 'probed_url' => $ret['url'], 'last-item' => $ret['last-item'], 'callstack' => System::callstack(20)]);
|
||||
}
|
||||
|
||||
@@ -488,39 +488,6 @@ class Post
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select pinned rows from the post-thread-user table for a given user
|
||||
*
|
||||
* @param integer $uid User ID
|
||||
* @param array $selected Array of selected fields, empty for all
|
||||
* @param array $condition Array of fields for condition
|
||||
* @param array $params Array of several parameters
|
||||
*
|
||||
* @return boolean|object
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function selectPinned(int $uid, array $selected = [], array $condition = [], $params = [])
|
||||
{
|
||||
$postthreaduser = DBA::select('post-thread-user', ['uri-id'], ['uid' => $uid, 'pinned' => true]);
|
||||
if (!DBA::isResult($postthreaduser)) {
|
||||
return $postthreaduser;
|
||||
}
|
||||
|
||||
$pinned = [];
|
||||
while ($useritem = DBA::fetch($postthreaduser)) {
|
||||
$pinned[] = $useritem['uri-id'];
|
||||
}
|
||||
DBA::close($postthreaduser);
|
||||
|
||||
if (empty($pinned)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$condition = DBA::mergeConditions(['uri-id' => $pinned, 'uid' => $uid, 'gravity' => GRAVITY_PARENT], $condition);
|
||||
|
||||
return self::selectForUser($uid, $selected, $condition, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update existing post entries
|
||||
*
|
||||
|
||||
@@ -123,31 +123,4 @@ class ThreadUser
|
||||
{
|
||||
DBA::update('post-thread-user', ['ignored' => $ignored], ['uri-id' => $uri_id, 'uid' => $uid], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uri_id
|
||||
* @param int $uid
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getPinned(int $uri_id, int $uid)
|
||||
{
|
||||
$threaduser = DBA::selectFirst('post-thread-user', ['pinned'], ['uri-id' => $uri_id, 'uid' => $uid]);
|
||||
if (empty($threaduser)) {
|
||||
return false;
|
||||
}
|
||||
return (bool)$threaduser['pinned'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uri_id
|
||||
* @param int $uid
|
||||
* @param int $pinned
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function setPinned(int $uri_id, int $uid, int $pinned)
|
||||
{
|
||||
DBA::update('post-thread-user', ['pinned' => $pinned], ['uri-id' => $uri_id, 'uid' => $uid], true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ class Statuses extends BaseApi
|
||||
}
|
||||
|
||||
if ($request['pinned']) {
|
||||
$condition = DBA::mergeConditions($condition, ['pinned' => true]);
|
||||
$condition = DBA::mergeConditions($condition, ['featured' => true]);
|
||||
}
|
||||
|
||||
if ($request['exclude_replies']) {
|
||||
|
||||
@@ -46,11 +46,7 @@ class Pin extends BaseApi
|
||||
DI::mstdnError()->RecordNotFound();
|
||||
}
|
||||
|
||||
if ($item['gravity'] != GRAVITY_PARENT) {
|
||||
DI::mstdnError()->UnprocessableEntity(DI::l10n()->t('Only starting posts can be pinned'));
|
||||
}
|
||||
|
||||
Post\ThreadUser::setPinned($this->parameters['id'], $uid, true);
|
||||
Post\Collection::add($this->parameters['id'], Post\Collection::FEATURED);
|
||||
|
||||
System::jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid)->toArray());
|
||||
}
|
||||
|
||||
@@ -46,11 +46,7 @@ class Unpin extends BaseApi
|
||||
DI::mstdnError()->RecordNotFound();
|
||||
}
|
||||
|
||||
if ($item['gravity'] != GRAVITY_PARENT) {
|
||||
DI::mstdnError()->UnprocessableEntity(DI::l10n()->t('Only starting posts can be pinned'));
|
||||
}
|
||||
|
||||
Post\ThreadUser::setPinned($this->parameters['id'], $uid, false);
|
||||
Post\Collection::remove($this->parameters['id'], Post\Collection::FEATURED);
|
||||
|
||||
System::jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid)->toArray());
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class Pin extends BaseModule
|
||||
|
||||
$itemId = intval($this->parameters['id']);
|
||||
|
||||
$item = Post::selectFirst(['uri-id', 'uid'], ['id' => $itemId]);
|
||||
$item = Post::selectFirst(['uri-id', 'uid', 'featured'], ['id' => $itemId]);
|
||||
if (!DBA::isResult($item)) {
|
||||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
@@ -57,9 +57,13 @@ class Pin extends BaseModule
|
||||
throw new HttpException\ForbiddenException($l10n->t('Access denied.'));
|
||||
}
|
||||
|
||||
$pinned = !Post\ThreadUser::getPinned($item['uri-id'], local_user());
|
||||
$pinned = !$item['featured'];
|
||||
|
||||
Post\ThreadUser::setPinned($item['uri-id'], local_user(), $pinned);
|
||||
if ($pinned) {
|
||||
Post\Collection::add($item['uri-id'], Post\Collection::FEATURED);
|
||||
} else {
|
||||
Post\Collection::remove($item['uri-id'], Post\Collection::FEATURED);
|
||||
}
|
||||
|
||||
// See if we've been passed a return path to redirect to
|
||||
$return_path = $_REQUEST['return'] ?? '';
|
||||
|
||||
@@ -29,6 +29,7 @@ use Friendica\Core\Protocol;
|
||||
use Friendica\Core\Session;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Model\Post\Category;
|
||||
@@ -207,20 +208,8 @@ class Status extends BaseProfile
|
||||
$items = Post::toArray($items_stmt);
|
||||
|
||||
if ($pager->getStart() == 0 && !empty($profile['uid'])) {
|
||||
$condition = ['private' => [Item::PUBLIC, Item::UNLISTED]];
|
||||
$remote_user = Session::getRemoteContactID($profile['uid']);
|
||||
if (!empty($remote_user)) {
|
||||
$permissionSets = DI::permissionSet()->selectByContactId($remote_user, $profile['uid']);
|
||||
if (!empty($permissionSets)) {
|
||||
$condition = ['psid' => array_merge($permissionSets->column('id'),
|
||||
[DI::permissionSet()->selectPublicForUser($profile['uid'])->id])];
|
||||
}
|
||||
} elseif ($profile['uid'] == local_user()) {
|
||||
$condition = [];
|
||||
}
|
||||
|
||||
$pinned_items = Post::selectPinned($profile['uid'], ['uri-id', 'pinned'], $condition);
|
||||
$pinned = Post::toArray($pinned_items);
|
||||
$pcid = Contact::getPublicIdByUserId($profile['uid']);
|
||||
$pinned = DBA::selectToArray('collection-view', [], ['cid' => $pcid]);
|
||||
$items = array_merge($items, $pinned);
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -231,7 +231,7 @@ class Post
|
||||
|
||||
$origin = $item['origin'] || $item['parent-origin'];
|
||||
|
||||
if ($item['pinned']) {
|
||||
if (!empty($item['featured'])) {
|
||||
$pinned = DI::l10n()->t('Pinned item');
|
||||
}
|
||||
|
||||
@@ -343,14 +343,14 @@ class Post
|
||||
|
||||
if ($conv->getProfileOwner() == local_user() && ($item['uid'] != 0)) {
|
||||
if ($origin) {
|
||||
$ispinned = ($item['pinned'] ? 'pinned' : 'unpinned');
|
||||
$ispinned = ($item['featured'] ? 'pinned' : 'unpinned');
|
||||
|
||||
$pin = [
|
||||
'do' => DI::l10n()->t('Pin'),
|
||||
'undo' => DI::l10n()->t('Unpin'),
|
||||
'toggle' => DI::l10n()->t('Toggle pin status'),
|
||||
'classdo' => $item['pinned'] ? 'hidden' : '',
|
||||
'classundo' => $item['pinned'] ? '' : 'hidden',
|
||||
'classdo' => $item['featured'] ? 'hidden' : '',
|
||||
'classundo' => $item['featured'] ? '' : 'hidden',
|
||||
'pinned' => DI::l10n()->t('Pinned'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -977,6 +977,54 @@ class Processor
|
||||
return Mail::insert($msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch featured posts from a contact with the given url
|
||||
*
|
||||
* @param string $url
|
||||
* @return void
|
||||
*/
|
||||
public static function fetchFeaturedPosts(string $url)
|
||||
{
|
||||
Logger::info('Fetch featured posts', ['contact' => $url]);
|
||||
|
||||
$apcontact = APContact::getByURL($url);
|
||||
if (empty($apcontact['featured'])) {
|
||||
Logger::info('Contact does not have a featured collection', ['contact' => $url]);
|
||||
return;
|
||||
}
|
||||
|
||||
$featured = ActivityPub::fetchItems($apcontact['featured']);
|
||||
if (empty($featured)) {
|
||||
Logger::info('Contact does not have featured posts', ['contact' => $url]);
|
||||
return;
|
||||
}
|
||||
|
||||
$new = 0;
|
||||
$old = 0;
|
||||
|
||||
foreach ($featured as $post) {
|
||||
if (empty($post['id'])) {
|
||||
continue;
|
||||
}
|
||||
$id = Item::fetchByLink($post['id']);
|
||||
if (!empty($id)) {
|
||||
$item = Post::selectFirst(['uri-id', 'featured'], ['id' => $id]);
|
||||
if (!empty($item['uri-id'])) {
|
||||
if (!$item['featured']) {
|
||||
Post\Collection::add($item['uri-id'], Post\Collection::FEATURED);
|
||||
Logger::debug('Added featured post', ['uri-id' => $item['uri-id'], 'contact' => $url]);
|
||||
$new++;
|
||||
} else {
|
||||
Logger::debug('Post already had been featured', ['uri-id' => $item['uri-id'], 'contact' => $url]);
|
||||
$old++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logger::info('Fetched featured posts', ['new' => $new, 'old' => $old, 'contact' => $url]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches missing posts
|
||||
*
|
||||
|
||||
@@ -225,9 +225,11 @@ class ExpirePosts
|
||||
$uris = DBA::select('item-uri', ['id'], ["`id` IN
|
||||
(SELECT `uri-id` FROM `post-thread` WHERE `received` < ?
|
||||
AND NOT `uri-id` IN (SELECT `uri-id` FROM `post-thread-user`
|
||||
WHERE (`mention` OR `starred` OR `wall` OR `pinned`) AND `uri-id` = `post-thread`.`uri-id`)
|
||||
WHERE (`mention` OR `starred` OR `wall`) AND `uri-id` = `post-thread`.`uri-id`)
|
||||
AND NOT `uri-id` IN (SELECT `uri-id` FROM `post-category`
|
||||
WHERE `uri-id` = `post-thread`.`uri-id`)
|
||||
AND NOT `uri-id` IN (SELECT `uri-id` FROM `post-collection`
|
||||
WHERE `uri-id` = `post-thread`.`uri-id`)
|
||||
AND NOT `uri-id` IN (SELECT `uri-id` FROM `post-media`
|
||||
WHERE `uri-id` = `post-thread`.`uri-id`)
|
||||
AND NOT `uri-id` IN (SELECT `parent-uri-id` FROM `post-user` INNER JOIN `contact` ON `contact`.`id` = `contact-id` AND `notify_new_posts`
|
||||
|
||||
Reference in New Issue
Block a user