diff --git a/mod/display.php b/mod/display.php index 1a024c7685..fd508fcfc2 100644 --- a/mod/display.php +++ b/mod/display.php @@ -123,11 +123,9 @@ function display_init(App $a) function display_fetchauthor($item) { - if (Diaspora::isReshare($item['body'], true)) { - $shared = Item::getShareArray($item); - if (!empty($shared['profile'])) { - $contact = Contact::getByURLForUser($shared['profile'], Session::getLocalUser()); - } + $shared = Item::getShareArray($item); + if (empty($shared['comment']) && !empty($shared['guid']) && !empty($shared['profile'])) { + $contact = Contact::getByURLForUser($shared['profile'], Session::getLocalUser()); } if (empty($contact)) { diff --git a/mod/share.php b/mod/share.php index 1ebce5291f..237da9553a 100644 --- a/mod/share.php +++ b/mod/share.php @@ -42,7 +42,7 @@ function share_init(App $a) { System::exit(); } - $shared = BBCode::fetchShareAttributes($item['body']); + $shared = Item::getShareArray($item); if (empty($shared['comment']) && (!empty($shared['message_id']) || !empty($shared['link']))) { $content = '[share]' . ($shared['message_id'] ?: $shared['link']) . '[/share]'; } else { diff --git a/src/Content/Item.php b/src/Content/Item.php index 521c015468..2f780ec4e6 100644 --- a/src/Content/Item.php +++ b/src/Content/Item.php @@ -677,10 +677,10 @@ class Item $shared_content .= '[h3]' . $item['title'] . "[/h3]\n"; } - $shared = BBCode::fetchShareAttributes($item['body']); + $shared = ItemModel::getShareArray($item); // If it is a reshared post then reformat it to avoid display problems with two share elements - if (Diaspora::isReshare($item['body'], false)) { + if (!empty($shared)) { if (!empty($shared['guid']) && ($encaspulated_share = self::createSharedPostByGuid($shared['guid'], 0, '', $add_media))) { $item['body'] = preg_replace("/\[share.*?\](.*)\[\/share\]/ism", $encaspulated_share, $item['body']); } diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index d03161df9f..7394f5fd7b 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -1023,6 +1023,7 @@ class BBCode { DI::profiler()->startRecording('rendering'); if (preg_match('~(.*?)\[share](.*)\[/share]~ism', $text, $matches)) { + DI::profiler()->stopRecording(); return [ 'author' => '', 'profile' => '', @@ -1093,12 +1094,7 @@ class BBCode */ public static function removeSharedData(string $body): string { - return BBCode::convertShare( - $body, - function (array $attributes) { - return ''; - } - ); + return preg_replace("/\s*\[share .*?\].*?\[\/share\]\s*/ism", '', $body); } /** diff --git a/src/Factory/Api/Mastodon/Status.php b/src/Factory/Api/Mastodon/Status.php index 21ecee0f95..4e1f790f50 100644 --- a/src/Factory/Api/Mastodon/Status.php +++ b/src/Factory/Api/Mastodon/Status.php @@ -155,7 +155,7 @@ class Status extends BaseFactory $poll = null; } - $shared = BBCode::fetchShareAttributes($item['body']); + $shared = Item::getShareArray($item); if (!empty($shared['guid'])) { $shared_item = Post::selectFirst(['uri-id', 'plink'], ['guid' => $shared['guid']]); diff --git a/src/Factory/Api/Twitter/Status.php b/src/Factory/Api/Twitter/Status.php index a3ced8e58c..ac03172e89 100644 --- a/src/Factory/Api/Twitter/Status.php +++ b/src/Factory/Api/Twitter/Status.php @@ -178,7 +178,7 @@ class Status extends BaseFactory $friendica_activities = $this->activities->createFromUriId($item['uri-id'], $uid); - $shared = BBCode::fetchShareAttributes($item['body']); + $shared = Item::getShareArray($item); if (!empty($shared['guid'])) { $shared_item = Post::selectFirst(['uri-id', 'plink'], ['guid' => $shared['guid']]); diff --git a/src/Model/Contact.php b/src/Model/Contact.php index d8a5b387fd..143b3fcd4d 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -97,11 +97,11 @@ class Contact * Relationship types * @{ */ - const NOTHING = 0; - const FOLLOWER = 1; - const SHARING = 2; - const FRIEND = 3; - const SELF = 4; + const NOTHING = 0; // There is no relationship between the contact and the user + const FOLLOWER = 1; // The contact is following this user + const SHARING = 2; // The contact shares their content with this user + const FRIEND = 3; // There is a mutual relationship between the contact and the user + const SELF = 4; // This is the user theirself /** * @} */ diff --git a/src/Model/Item.php b/src/Model/Item.php index e53d64d5e1..563356313a 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -113,7 +113,7 @@ class Item 'private', 'title', 'body', 'raw-body', 'location', 'coord', 'app', 'inform', 'deleted', 'extid', 'post-type', 'post-reason', 'gravity', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', - 'author-id', 'author-link', 'author-name', 'author-avatar', 'owner-id', 'owner-link', 'contact-uid', + 'author-id', 'author-addr', 'author-link', 'author-name', 'author-avatar', 'owner-id', 'owner-link', 'contact-uid', 'signed_text', 'network', 'wall', 'contact-id', 'plink', 'origin', 'thr-parent-id', 'parent-uri-id', 'quote-uri', 'quote-uri-id', 'postopts', 'pubmail', 'event-created', 'event-edited', 'event-start', 'event-finish', @@ -2950,7 +2950,7 @@ class Item $item['mentions'] = $tags['mentions']; $body = $item['body'] ?? ''; - $shared = BBCode::fetchShareAttributes($body); + $shared = self::getShareArray($item); if (!empty($shared['guid'])) { $shared_item = Post::selectFirst(['uri-id', 'guid', 'plink', 'has-media'], ['guid' => $shared['guid'], 'uid' => [$item['uid'], 0]]); } @@ -3043,7 +3043,7 @@ class Item $s = self::addVisualAttachments($shared_attachments, $item, $s, true); $s = self::addLinkAttachment($shared_uri_id ?: $item['uri-id'], $shared_attachments, $body, $s, true, []); $s = self::addNonVisualAttachments($shared_attachments, $item, $s, true); - $body = preg_replace("/\s*\[share .*?\].*?\[\/share\]\s*/ism", '', $body); + $body = BBCode::removeSharedData($body); } $s = self::addVisualAttachments($attachments, $item, $s, false); @@ -3601,7 +3601,29 @@ class Item */ public static function getShareArray(array $item): array { - return BBCode::fetchShareAttributes($item['body']); + $attributes = BBCode::fetchShareAttributes($item['body'] ?? ''); + if (!empty($attributes)) { + return $attributes; + } + + if (!empty($item['quote-uri-id'])) { + $shared = Post::selectFirst(['author-name', 'author-link', 'author-avatar', 'plink', 'created', 'guid', 'uri', 'body'], ['uri-id' => $item['quote-uri-id']]); + if (!empty($shared)) { + return [ + 'author' => $shared['author-name'], + 'profile' => $shared['author-link'], + 'avatar' => $shared['author-avatar'], + 'link' => $shared['plink'], + 'posted' => $shared['created'], + 'guid' => $shared['guid'], + 'message_id' => $shared['uri'], + 'comment' => $item['body'], + 'shared' => $shared['body'], + ]; + } + } + + return []; } /** diff --git a/src/Model/Post/Media.php b/src/Model/Post/Media.php index 6d0707743e..8d86bc757c 100644 --- a/src/Model/Post/Media.php +++ b/src/Model/Post/Media.php @@ -406,7 +406,7 @@ class Media // Only remove the shared data from "real" reshares $shared = BBCode::fetchShareAttributes($body); if (!empty($shared['guid'])) { - $unshared_body = preg_replace("/\s*\[share .*?\].*?\[\/share\]\s*/ism", '', $body); + $unshared_body = BBCode::removeSharedData($body); } $attachments = []; @@ -489,7 +489,7 @@ class Media $shared = BBCode::fetchShareAttributes($body); if (!empty($shared['guid'])) { // Don't look at the shared content - $body = preg_replace("/\s*\[share .*?\].*?\[\/share\]\s*/ism", '', $body); + $body = BBCode::removeSharedData($body); } // Remove all hashtags and mentions @@ -522,7 +522,7 @@ class Media public static function insertFromAttachmentData(int $uriid, string $body) { // Don't look at the shared content - $body = preg_replace("/\s*\[share .*?\].*?\[\/share\]\s*/ism", '', $body); + $body = BBCode::removeSharedData($body); $data = BBCode::getAttachmentData($body); if (empty($data)) { diff --git a/src/Model/Tag.php b/src/Model/Tag.php index 435dfda7cb..6611245a0c 100644 --- a/src/Model/Tag.php +++ b/src/Model/Tag.php @@ -311,10 +311,8 @@ class Tag // Only remove the shared data from "real" reshares $shared = BBCode::fetchShareAttributes($body); if (!empty($shared['guid'])) { - if (preg_match("/\s*\[share .*?\](.*?)\[\/share\]\s*/ism", $body, $matches)) { - $share_body = $matches[1]; - } - $body = preg_replace("/\s*\[share .*?\].*?\[\/share\]\s*/ism", '', $body); + $share_body = $shared['shared']; + $body = BBCode::removeSharedData($body); } foreach (self::getFromBody($body, $tags) as $tag) { diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 8b07d12e7d..cc7774b23a 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -1664,17 +1664,18 @@ class Transmitter $body = preg_replace("/\s*\[attachment .*?\].*?\[\/attachment\]\s*/ism", '', $body); } - $body = BBCode::setMentionsToNicknames($body); + $body = BBCode::setMentionsToNicknames($body); + $shared = BBCode::fetchShareAttributes($body); if (!empty($item['quote-uri']) && Post::exists(['uri-id' => $item['quote-uri-id'], 'network' => [Protocol::ACTIVITYPUB, Protocol::DFRN]])) { $real_quote = true; - if (Diaspora::isReshare($body, false)) { + if (!empty($shared['link'])) { $body = BBCode::replaceSharedData($body); } elseif (strpos($body, $item['quote-uri']) === false) { $body .= "\n♲ " . $item['quote-uri']; } $data['quoteUrl'] = $item['quote-uri']; - } elseif (!empty($item['quote-uri']) && !Diaspora::isReshare($body, false)) { + } elseif (!empty($item['quote-uri']) && empty($shared)) { $body .= "\n" . DI::contentItem()->createSharedPostByUriId($item['quote-uri-id'], $item['uid'], true); $item['body'] = Item::improveSharedDataInBody($item, true); } @@ -1691,8 +1692,10 @@ class Transmitter if ($real_quote) { $shared = BBCode::fetchShareAttributes($richbody); - if (!empty($shared['link']) && !empty($shared['guid']) && !empty($shared['comment'])) { + if (!empty($shared['link'])) { $richbody = BBCode::replaceSharedData($richbody); + } elseif (strpos($richbody, $item['quote-uri']) === false) { + $richbody .= "\n♲ " . $item['quote-uri']; } } diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index ee8edf0a04..b3108c8ff3 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -776,36 +776,6 @@ class Diaspora return ''; } - /** - * get a handle (user@domain.tld) from a given contact id - * - * @param int $contact_id The id in the contact table - * @param int $pcontact_id The id in the contact table (Used for the public contact) - * - * @return string the handle - * @throws \Exception - */ - private static function handleFromContact(int $contact_id, int $pcontact_id = 0): string - { - $handle = ''; - - if ($pcontact_id != 0) { - $contact = Contact::getById($pcontact_id, ['addr']); - if (DBA::isResult($contact)) { - $handle = $contact['addr']; - } - } - - if (empty($handle)) { - $contact = Contact::getById($contact_id, ['addr']); - if (DBA::isResult($contact)) { - $handle = $contact['addr']; - } - } - - return strtolower($handle); - } - /** * Get a contact id for a given handle * @@ -3203,59 +3173,35 @@ class Diaspora /** * Checks a message body if it is a reshare * - * @param string $body The message body that is to be check - * @param bool $complete Should it be a complete check or a simple check? + * @param array $item The message body that is to be check * - * @return array|bool Reshare details or "false" if no reshare + * @return array Reshare details or "false" if no reshare * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ - public static function isReshare(string $body, bool $complete = true) + public static function isReshare(array $item): array { - $body = trim($body); - - $reshared = Item::getShareArray(['body' => $body]); + $reshared = Item::getShareArray($item); if (empty($reshared)) { - return false; + return []; } - // Skip if it isn't a pure repeated messages - // Does it start with a share? - if (!empty($reshared['comment']) && $complete) { - return false; + // Skip if it isn't a pure repeated messages or not a real reshare + if (!empty($reshared['comment']) || empty($reshared['guid'])) { + return []; } - if (!empty($reshared['guid']) && $complete) { - $condition = ['guid' => $reshared['guid'], 'network' => [Protocol::DFRN, Protocol::DIASPORA]]; - $item = Post::selectFirst(['contact-id'], $condition); - if (DBA::isResult($item)) { - $ret = []; - $ret['root_handle'] = self::handleFromContact($item['contact-id']); - $ret['root_guid'] = $reshared['guid']; - return $ret; - } elseif ($complete) { - // We are resharing something that isn't a DFRN or Diaspora post. - // So we have to return "false" on "$complete" to not trigger a reshare. - return false; - } - } elseif (empty($reshared['guid']) && $complete) { - return false; + $condition = ['guid' => $reshared['guid'], 'network' => [Protocol::DFRN, Protocol::DIASPORA]]; + $item = Post::selectFirst(['author-addr'], $condition); + if (DBA::isResult($item)) { + return [ + 'root_handle' => strtolower($item['author-addr']), + 'root_guid' => $reshared['guid'] + ]; } - $ret = []; - - if (!empty($reshared['profile']) && ($cid = Contact::getIdForURL($reshared['profile']))) { - $contact = DBA::selectFirst('contact', ['addr'], ['id' => $cid]); - if (!empty($contact['addr'])) { - $ret['root_handle'] = $contact['addr']; - } - } - - if (empty($ret) && !$complete) { - return true; - } - - return $ret; + // We are resharing something that isn't a DFRN or Diaspora post. + return []; } /** @@ -3352,7 +3298,7 @@ class Diaspora $edited = DateTimeFormat::utc($item['edited'] ?? $item['created'], DateTimeFormat::ATOM); // Detect a share element and do a reshare - if (($item['private'] != Item::PRIVATE) && ($ret = self::isReshare($item['body']))) { + if (($item['private'] != Item::PRIVATE) && ($ret = self::isReshare($item))) { $message = [ 'author' => $myaddr, 'guid' => $item['guid'], @@ -3725,7 +3671,7 @@ class Diaspora */ public static function sendRetraction(array $item, array $owner, array $contact, bool $public_batch = false, bool $relay = false): int { - $itemaddr = self::handleFromContact($item['contact-id'], $item['author-id']); + $itemaddr = strtolower($item['author-addr']); $msg_type = 'retraction'; diff --git a/src/Protocol/Feed.php b/src/Protocol/Feed.php index e5f205aa5a..7c6a68b601 100644 --- a/src/Protocol/Feed.php +++ b/src/Protocol/Feed.php @@ -438,7 +438,7 @@ class Feed } if (!empty($href)) { - $attachment = ['type' => Post\Media::UNKNOWN, 'url' => $href, 'mimetype' => $type, 'size' => $length]; + $attachment = ['uri-id' => -1, 'type' => Post\Media::UNKNOWN, 'url' => $href, 'mimetype' => $type, 'size' => $length]; $attachment = Post\Media::fetchAdditionalData($attachment); diff --git a/src/Worker/Delivery.php b/src/Worker/Delivery.php index fa0121c831..f51f5f205b 100644 --- a/src/Worker/Delivery.php +++ b/src/Worker/Delivery.php @@ -274,7 +274,7 @@ class Delivery private static function deliverDFRN(string $cmd, array $contact, array $owner, array $items, array $target_item, bool $public_message, bool $top_level, bool $followup, int $server_protocol = null) { // Transmit Diaspora reshares via Diaspora if the Friendica contact support Diaspora - if (Diaspora::isReshare($target_item['body'] ?? '') && !empty(FContact::getByURL($contact['addr'], false))) { + if (Diaspora::isReshare($target_item ?? []) && !empty(FContact::getByURL($contact['addr'], false))) { Logger::info('Reshare will be transmitted via Diaspora', ['url' => $contact['url'], 'guid' => ($target_item['guid'] ?? '') ?: $target_item['id']]); self::deliverDiaspora($cmd, $contact, $owner, $items, $target_item, $public_message, $top_level, $followup); return;