X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=src%2FModel%2FItem.php;h=88c973efdab2afc41c6eb0f74716ad9b3f164403;hb=aed5e4cc960797a25f184d24d7c81265e05d4ee6;hp=9d142facc00643cc944e38b377e9ba0f456d6479;hpb=3666742e7b1f1c64fb0632d2df799da11c763229;p=friendica.git diff --git a/src/Model/Item.php b/src/Model/Item.php index 9d142facc0..88c973efda 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -21,7 +21,6 @@ namespace Friendica\Model; -use Friendica\Content\PageInfo; use Friendica\Content\Text\BBCode; use Friendica\Content\Text\HTML; use Friendica\Core\Hook; @@ -160,6 +159,10 @@ class Item $fields['vid'] = Verb::getID($fields['verb']); } + if (!empty($fields['edited'])) { + $previous = Post::selectFirst(['edited'], $condition); + } + $rows = Post::update($fields, $condition); if (is_bool($rows)) { return $rows; @@ -173,7 +176,7 @@ class Item Logger::info('Updating per single row method', ['fields' => $fields, 'condition' => $condition]); - $items = Post::select(['id', 'origin', 'uri-id', 'uid'], $condition); + $items = Post::select(['id', 'origin', 'uri-id', 'uid', 'author-network'], $condition); $notify_items = []; @@ -184,9 +187,15 @@ class Item $content_fields = ['raw-body' => trim($fields['raw-body'] ?? $fields['body'])]; // Remove all media attachments from the body and store them in the post-media table - // @todo On shared postings (Diaspora style and commented reshare) don't fetch content from rhe shared part + // @todo On shared postings (Diaspora style and commented reshare) don't fetch content from the shared part $content_fields['raw-body'] = Post\Media::insertFromBody($item['uri-id'], $content_fields['raw-body']); $content_fields['raw-body'] = self::setHashtags($content_fields['raw-body']); + + if ($item['author-network'] != Protocol::DFRN) { + Post\Media::insertFromRelevantUrl($item['uri-id'], $content_fields['raw-body']); + } + + Post\Content::update($item['uri-id'], $content_fields); } if (!empty($fields['file'])) { @@ -198,8 +207,8 @@ class Item } // We only need to notfiy others when it is an original entry from us. - // Only call the notifier when the item has some content relevant change. - if ($item['origin'] && in_array('edited', array_keys($fields))) { + // Only call the notifier when the item had been edited and records had been changed. + if ($item['origin'] && !empty($fields['edited']) && ($previous['edited'] != $fields['edited'])) { $notify_items[] = $item['id']; } } @@ -513,7 +522,7 @@ class Item public static function isValid(array $item) { // When there is no content then we don't post it - if (($item['body'] . $item['title'] == '') && !Post\Media::existsByURIId($item['uri-id'])) { + if (($item['body'] . $item['title'] == '') && (empty($item['uri-id']) || !Post\Media::existsByURIId($item['uri-id']))) { Logger::notice('No body, no title.'); return false; } @@ -929,7 +938,25 @@ class Item if ($notify) { $item['edit'] = false; $item['parent'] = $parent_id; + + // Trigger automatic reactions for addons + $item['api_source'] = true; + + // We have to tell the hooks who we are - this really should be improved + if (!local_user()) { + $_SESSION['authenticated'] = true; + $_SESSION['uid'] = $uid; + $dummy_session = true; + } else { + $dummy_session = false; + } + Hook::callAll('post_local', $item); + + if ($dummy_session) { + unset($_SESSION['authenticated']); + unset($_SESSION['uid']); + } } else { Hook::callAll('post_remote', $item); } @@ -960,18 +987,27 @@ class Item self::setOwnerforResharedItem($item); } + if (isset($item['attachments'])) { + foreach ($item['attachments'] as $attachment) { + $attachment['uri-id'] = $item['uri-id']; + Post\Media::insert($attachment); + } + unset($item['attachments']); + } + Post\Media::insertFromAttachmentData($item['uri-id'], $item['body']); // Remove all media attachments from the body and store them in the post-media table $item['raw-body'] = Post\Media::insertFromBody($item['uri-id'], $item['raw-body']); $item['raw-body'] = self::setHashtags($item['raw-body']); + if (!DBA::exists('contact', ['id' => $item['author-id'], 'network' => Protocol::DFRN])) { + Post\Media::insertFromRelevantUrl($item['uri-id'], $item['raw-body']); + } + // Check for hashtags in the body and repair or add hashtag links $item['body'] = self::setHashtags($item['body']); - // Fill the cache field - self::putInCache($item); - if (stristr($item['verb'], Activity::POKE)) { $notify_type = Delivery::POKE; } else { @@ -985,6 +1021,30 @@ class Item if (empty($item['event-id'])) { unset($item['event-id']); + + $ev = Event::fromBBCode($item['body']); + if ((!empty($ev['desc']) || !empty($ev['summary'])) && !empty($ev['start'])) { + Logger::info('Event found.'); + $ev['cid'] = $item['contact-id']; + $ev['uid'] = $item['uid']; + $ev['uri'] = $item['uri']; + $ev['edited'] = $item['edited']; + $ev['private'] = $item['private']; + $ev['guid'] = $item['guid']; + $ev['plink'] = $item['plink']; + $ev['network'] = $item['network']; + $ev['protocol'] = $item['protocol']; + $ev['direction'] = $item['direction']; + $ev['source'] = $item['source']; + + $event = DBA::selectFirst('event', ['id'], ['uri' => $item['uri'], 'uid' => $item['uid']]); + if (DBA::isResult($event)) { + $ev['id'] = $event['id']; + } + + $item['event-id'] = Event::store($ev); + Logger::info('Event was stored', ['id' => $item['event-id']]); + } } if (empty($item['causer-id'])) { @@ -1001,7 +1061,14 @@ class Item Post\Content::insert($item['uri-id'], $item); } - // Diaspora signature + // Create Diaspora signature + if ($item['origin'] && empty($item['diaspora_signed_text']) && ($item['gravity'] != GRAVITY_PARENT)) { + $signed = Diaspora::createCommentSignature($uid, $item); + if (!empty($signed)) { + $item['diaspora_signed_text'] = json_encode($signed); + } + } + if (!empty($item['diaspora_signed_text'])) { DBA::replace('diaspora-interaction', ['uri-id' => $item['uri-id'], 'interaction' => $item['diaspora_signed_text']]); } @@ -1161,13 +1228,10 @@ class Item Logger::info('The resharer is no forum: quit', ['resharer' => $item['author-id'], 'owner' => $parent['owner-id'], 'author' => $parent['author-id'], 'uid' => $item['uid']]); return; } - self::update(['post-reason' => self::PR_ANNOUNCEMENT, 'causer-id' => $item['author-id']], ['id' => $parent['id']]); - Logger::info('Set announcement post-reason', ['uri-id' => $item['uri-id'], 'thr-parent-id' => $item['thr-parent-id'], 'uid' => $item['uid']]); - return; } - self::update(['owner-id' => $item['author-id'], 'contact-id' => $cid], ['id' => $parent['id']]); - Logger::info('Change owner of the parent', ['uri-id' => $item['uri-id'], 'thr-parent-id' => $item['thr-parent-id'], 'uid' => $item['uid'], 'owner-id' => $item['author-id'], 'contact-id' => $cid]); + self::update(['post-reason' => self::PR_ANNOUNCEMENT, 'causer-id' => $item['author-id']], ['id' => $parent['id']]); + Logger::info('Set announcement post-reason', ['uri-id' => $item['uri-id'], 'thr-parent-id' => $item['thr-parent-id'], 'uid' => $item['uid']]); } /** @@ -1289,19 +1353,26 @@ class Item /** * Store a public item defined by their URI-ID for the given users * - * @param integer $uri_id URI-ID of the given item - * @param integer $uid The user that will receive the item entry - * @param array $fields Additional fields to be stored + * @param integer $uri_id URI-ID of the given item + * @param integer $uid The user that will receive the item entry + * @param array $fields Additional fields to be stored + * @param integer $source_uid User id of the source post * @return integer stored item id */ - public static function storeForUserByUriId(int $uri_id, int $uid, array $fields = []) + public static function storeForUserByUriId(int $uri_id, int $uid, array $fields = [], int $source_uid = 0) { - $item = Post::selectFirst(self::ITEM_FIELDLIST, ['uri-id' => $uri_id, 'uid' => 0]); + if ($uid == $source_uid) { + Logger::warning('target UID must not be be equal to the source UID', ['uri-id' => $uri_id, 'uid' => $uid]); + return 0; + } + + $item = Post::selectFirst(self::ITEM_FIELDLIST, ['uri-id' => $uri_id, 'uid' => $source_uid]); if (!DBA::isResult($item)) { + Logger::warning('Item could not be fetched', ['uri-id' => $uri_id, 'uid' => $source_uid]); return 0; } - if (($item['private'] == self::PRIVATE) || !in_array($item['network'], Protocol::FEDERATED)) { + if (($source_uid == 0) && (($item['private'] == self::PRIVATE) || !in_array($item['network'], Protocol::FEDERATED))) { Logger::notice('Item is private or not from a federated network. It will not be stored for the user.', ['uri-id' => $uri_id, 'uid' => $uid, 'private' => $item['private'], 'network' => $item['network']]); return 0; } @@ -1310,8 +1381,25 @@ class Item $item = array_merge($item, $fields); + $is_reshare = ($item['gravity'] == GRAVITY_ACTIVITY) && ($item['verb'] == Activity::ANNOUNCE); + + if ((($item['gravity'] == GRAVITY_PARENT) || $is_reshare) && + DI::pConfig()->get($uid, 'system', 'accept_only_sharer') && + !Contact::isSharingByURL($item['author-link'], $uid) && + !Contact::isSharingByURL($item['owner-link'], $uid)) { + Logger::info('Contact is not a follower, thread will not be stored', ['author' => $item['author-link'], 'uid' => $uid]); + return 0; + } + + if ((($item['gravity'] == GRAVITY_COMMENT) || $is_reshare) && !Post::exists(['uri-id' => $item['thr-parent-id'], 'uid' => $uid])) { + // Only do an auto complete with the source uid "0" to prevent privavy problems + $causer = $item['causer-id'] ?: $item['author-id']; + $result = self::storeForUserByUriId($item['thr-parent-id'], $uid, ['causer-id' => $causer, 'post-reason' => self::PR_FETCHED]); + Logger::info('Fetched thread parent', ['uri-id' => $item['thr-parent-id'], 'uid' => $uid, 'causer' => $causer, 'result' => $result]); + } + $stored = self::storeForUser($item, $uid); - Logger::info('Public item stored for user', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'stored' => $stored]); + Logger::info('Item stored for user', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'source-uid' => $source_uid, 'stored' => $stored]); return $stored; } @@ -1331,11 +1419,18 @@ class Item } unset($item['id']); - unset($item['parent']); unset($item['mention']); unset($item['starred']); unset($item['unseen']); unset($item['psid']); + unset($item['pinned']); + unset($item['ignored']); + unset($item['pubmail']); + unset($item['forum_mode']); + + unset($item['event-id']); + unset($item['hidden']); + unset($item['notification-type']); $item['uid'] = $uid; $item['origin'] = 0; @@ -1361,8 +1456,6 @@ class Item $item['contact-id'] = $self['id']; } - /// @todo Handling of "event-id" - $notify = false; if ($item['gravity'] == GRAVITY_PARENT) { $contact = DBA::selectFirst('contact', [], ['id' => $item['contact-id'], 'self' => false]); @@ -1374,9 +1467,9 @@ class Item $distributed = self::insert($item, $notify, true); if (!$distributed) { - Logger::info("Distributed public item wasn't stored", ['uri-id' => $item['uri-id'], 'user' => $uid]); + Logger::info("Distributed item wasn't stored", ['uri-id' => $item['uri-id'], 'user' => $uid]); } else { - Logger::info('Distributed public item was stored', ['uri-id' => $item['uri-id'], 'user' => $uid, 'stored' => $distributed]); + Logger::info('Distributed item was stored', ['uri-id' => $item['uri-id'], 'user' => $uid, 'stored' => $distributed]); } return $distributed; } @@ -1817,6 +1910,15 @@ class Item return false; } + self::performActivity($item['id'], 'announce', $uid); + + /** + * All the following lines are only needed for private forums and compatibility to older systems without AP support. + * A possible way would be that the followers list of a forum would always be readable by all followers. + * So this would mean that the comment distribution could be done exactly for the intended audience. + * Or possibly we could store the receivers that had been in the "announce" message above and use this. + */ + // now change this copy of the post to a forum head message and deliver to all the tgroup members $self = DBA::selectFirst('contact', ['id', 'name', 'url', 'thumb'], ['uid' => $uid, 'self' => true]); if (!DBA::isResult($self)) { @@ -1826,8 +1928,13 @@ class Item $owner_id = Contact::getIdForURL($self['url']); // also reset all the privacy bits to the forum default permissions - - $private = ($user['allow_cid'] || $user['allow_gid'] || $user['deny_cid'] || $user['deny_gid']) ? self::PRIVATE : self::PUBLIC; + if ($user['allow_cid'] || $user['allow_gid'] || $user['deny_cid'] || $user['deny_gid']) { + $private = self::PRIVATE; + } elseif (DI::pConfig()->get($user['uid'], 'system', 'unlisted')) { + $private = self::UNLISTED; + } else { + $private = self::PUBLIC; + } $psid = PermissionSet::getIdFromACL( $user['uid'], @@ -1845,8 +1952,6 @@ class Item Worker::add(['priority' => PRIORITY_HIGH, 'dont_fork' => true], 'Notifier', Delivery::POST, (int)$item['uri-id'], (int)$item['uid']); - self::performActivity($item['id'], 'announce', $uid); - return false; } @@ -1956,13 +2061,6 @@ class Item $result = true; } - // Trigger automatic reactions for addons - $datarray['api_source'] = true; - - // We have to tell the hooks who we are - this really should be improved - $_SESSION['authenticated'] = true; - $_SESSION['uid'] = $contact['uid']; - return (bool)$result; } @@ -2641,7 +2739,25 @@ class Item } $body = $item['body'] ?? ''; - $item['body'] = preg_replace("/\s*\[attachment .*?\].*?\[\/attachment\]\s*/ism", '', $item['body']); + $shared = BBCode::fetchShareAttributes($body); + if (!empty($shared['guid'])) { + $shared_item = Post::selectFirst(['uri-id', 'plink'], ['guid' => $shared['guid']]); + $shared_uri_id = $shared_item['uri-id'] ?? 0; + $shared_links = [strtolower($shared_item['plink'] ?? '')]; + $shared_attachments = Post\Media::splitAttachments($shared_uri_id, $shared['guid']); + $shared_links = array_merge($shared_links, array_column($shared_attachments['visual'], 'url')); + $shared_links = array_merge($shared_links, array_column($shared_attachments['link'], 'url')); + $shared_links = array_merge($shared_links, array_column($shared_attachments['additional'], 'url')); + $item['body'] = self::replaceVisualAttachments($shared_attachments, $item['body']); + } else { + $shared_uri_id = 0; + $shared_links = []; + } + $attachments = Post\Media::splitAttachments($item['uri-id'], $item['guid'] ?? '', $shared_links); + $item['body'] = self::replaceVisualAttachments($attachments, $item['body'] ?? ''); + $item['body'] = Post\Link::insertFromBody($item['uri-id'], $item['body']); + + $item['body'] = preg_replace("/\s*\[attachment .*?\].*?\[\/attachment\]\s*/ism", "\n", $item['body']); self::putInCache($item); $item['body'] = $body; $s = $item["rendered-html"]; @@ -2663,27 +2779,15 @@ class Item return $s; } - $shared = BBCode::fetchShareAttributes($item['body']); - if (!empty($shared['guid'])) { - $shared_item = Post::selectFirst(['uri-id', 'plink'], ['guid' => $shared['guid']]); - $shared_uri_id = $shared_item['uri-id'] ?? 0; - $shared_links = [strtolower($shared_item['plink'] ?? '')]; - $attachments = Post\Media::splitAttachments($shared_uri_id, $shared['guid']); - $s = self::addVisualAttachments($attachments, $item, $s, true); - $s = self::addLinkAttachment($attachments, $body, $s, true, []); - $s = self::addNonVisualAttachments($attachments, $item, $s, true); - $shared_links = array_merge($shared_links, array_column($attachments['visual'], 'url')); - $shared_links = array_merge($shared_links, array_column($attachments['link'], 'url')); - $shared_links = array_merge($shared_links, array_column($attachments['additional'], 'url')); + if (!empty($shared_attachments)) { + $s = self::addVisualAttachments($shared_attachments, $item, $s, true); + $s = self::addLinkAttachment($shared_uri_id, $shared_attachments, $body, $s, true, []); + $s = self::addNonVisualAttachments($shared_attachments, $item, $s, true); $body = preg_replace("/\s*\[share .*?\].*?\[\/share\]\s*/ism", '', $body); - } else { - $shared_uri_id = 0; - $shared_links = []; } - $attachments = Post\Media::splitAttachments($item['uri-id'], $item['guid'], $shared_links); $s = self::addVisualAttachments($attachments, $item, $s, false); - $s = self::addLinkAttachment($attachments, $body, $s, false, $shared_links); + $s = self::addLinkAttachment($item['uri-id'], $attachments, $body, $s, false, $shared_links); $s = self::addNonVisualAttachments($attachments, $item, $s, false); // Map. @@ -2713,10 +2817,23 @@ class Item * * @param string $body * @param string $url + * @param int $type * @return bool */ - public static function containsLink(string $body, string $url) + public static function containsLink(string $body, string $url, int $type = 0) { + // Make sure that for example site parameters aren't used when testing if the link is contained in the body + $urlparts = parse_url($url); + unset($urlparts['query']); + unset($urlparts['fragment']); + $url = Network::unparseURL($urlparts); + + // Remove media links to only search in embedded content + // @todo Check images for image link, audio for audio links, ... + if (in_array($type, [Post\Media::AUDIO, Post\Media::VIDEO, Post\Media::IMAGE])) { + $body = preg_replace("/\[url=[^\[\]]*\](.*)\[\/url\]/Usi", ' $1 ', $body); + } + if (strpos($body, $url)) { return true; } @@ -2729,6 +2846,28 @@ class Item return false; } + /** + * Replace visual attachments in the body + * + * @param array $attachments + * @param string $body + * @return string modified body + */ + private static function replaceVisualAttachments(array $attachments, string $body) + { + $stamp1 = microtime(true); + + foreach ($attachments['visual'] as $attachment) { + if (!empty($attachment['preview'])) { + $body = str_replace($attachment['preview'], Post\Media::getPreviewUrlForId($attachment['id'], Proxy::SIZE_LARGE), $body); + } elseif ($attachment['filetype'] == 'image') { + $body = str_replace($attachment['url'], Post\Media::getUrlForId($attachment['id']), $body); + } + } + DI::profiler()->saveTimestamp($stamp1, 'rendering'); + return $body; + } + /** * Add visual attachments to the content * @@ -2745,16 +2884,12 @@ class Item // @todo In the future we should make a single for the template engine with all media in it. This allows more flexibilty. foreach ($attachments['visual'] as $attachment) { - if (self::containsLink($item['body'], $attachment['url'])) { + if (self::containsLink($item['body'], $attachment['url'], $attachment['type'])) { continue; } - $author = ['uid' => 0, 'id' => $item['author-id'], - 'network' => $item['author-network'], 'url' => $item['author-link']]; - $the_url = Contact::magicLinkByContact($author, $attachment['url']); - if (!empty($attachment['preview'])) { - $preview_url = Proxy::proxifyUrl(Contact::magicLinkByContact($author, $attachment['preview'])); + $preview_url = Post\Media::getPreviewUrlForId($attachment['id'], Proxy::SIZE_LARGE); } else { $preview_url = ''; } @@ -2764,13 +2899,13 @@ class Item $media = Renderer::replaceMacros(Renderer::getMarkupTemplate('video_top.tpl'), [ '$video' => [ 'id' => $attachment['id'], - 'src' => $the_url, + 'src' => $attachment['url'], 'name' => $attachment['name'] ?: $attachment['url'], 'preview' => $preview_url, 'mime' => $attachment['mimetype'], ], ]); - if ($item['post-type'] == Item::PT_VIDEO) { + if (($item['post-type'] ?? null) == Item::PT_VIDEO) { $leading .= $media; } else { $trailing .= $media; @@ -2779,25 +2914,22 @@ class Item $media = Renderer::replaceMacros(Renderer::getMarkupTemplate('content/audio.tpl'), [ '$audio' => [ 'id' => $attachment['id'], - 'src' => $the_url, - 'name' => $attachment['name'] ?: $attachment['url'], + 'src' => $attachment['url'], + 'name' => $attachment['name'] ?: $attachment['url'], 'mime' => $attachment['mimetype'], ], ]); - if ($item['post-type'] == Item::PT_AUDIO) { + if (($item['post-type'] ?? null) == Item::PT_AUDIO) { $leading .= $media; } else { $trailing .= $media; } } elseif ($attachment['filetype'] == 'image') { - if (empty($preview_url) && (max($attachment['width'], $attachment['height']) > 600)) { - $preview_url = Proxy::proxifyUrl($the_url, false, ($attachment['width'] > $attachment['height']) ? Proxy::SIZE_MEDIUM : Proxy::SIZE_LARGE); - } $media = Renderer::replaceMacros(Renderer::getMarkupTemplate('content/image.tpl'), [ '$image' => [ - 'src' => Proxy::proxifyUrl($the_url), - 'preview' => $preview_url, - 'attachment' => $attachment, + 'src' => Post\Media::getUrlForId($attachment['id']), + 'preview' => Post\Media::getPreviewUrlForId($attachment['id'], ($attachment['width'] > $attachment['height']) ? Proxy::SIZE_MEDIUM : Proxy::SIZE_LARGE), + 'attachment' => $attachment, ], ]); // On Diaspora posts the attached pictures are leading @@ -2833,10 +2965,10 @@ class Item * @param string $body * @param string $content * @param bool $shared - * @param array $ignore_links + * @param array $ignore_links A list of URLs to ignore * @return string modified content */ - private static function addLinkAttachment(array $attachments, string $body, string $content, bool $shared, array $ignore_links) + private static function addLinkAttachment(int $uriid, array $attachments, string $body, string $content, bool $shared, array $ignore_links) { $stamp1 = microtime(true); // @ToDo Check only for audio and video @@ -2850,7 +2982,11 @@ class Item $found = true; } } - if (!$found) { + // @todo Judge between the links to use the one with most information + if (!$found && (empty($attachment) || !empty($link['author-name']) || + (empty($attachment['name']) && !empty($link['name'])) || + (empty($attachment['description']) && !empty($link['description'])) || + (empty($attachment['preview']) && !empty($link['preview'])))) { $attachment = $link; } } @@ -2871,21 +3007,71 @@ class Item 'type' => 'link', 'url' => $attachment['url']]; - if ($preview) { + if ($preview && !empty($attachment['preview'])) { if ($attachment['preview-width'] >= 500) { - $data['image'] = $attachment['preview'] ?? ''; + $data['image'] = Post\Media::getPreviewUrlForId($attachment['id'], Proxy::SIZE_MEDIUM); } else { - $data['preview'] = $attachment['preview'] ?? ''; + $data['preview'] = Post\Media::getPreviewUrlForId($attachment['id'], Proxy::SIZE_MEDIUM); } } + + if (!empty($data['description']) && !empty($content)) { + similar_text($data['description'], $content, $percent); + } else { + $percent = 0; + } + + if (!empty($data['description']) && (($data['title'] == $data['description']) || ($percent > 95) || (strpos($content, $data['description']) !== false))) { + $data['description'] = ''; + } + + if (($data['author_name'] ?? '') == ($data['provider_name'] ?? '')) { + $data['author_name'] = ''; + } + + if (($data['author_url'] ?? '') == ($data['provider_url'] ?? '')) { + $data['author_url'] = ''; + } } elseif (preg_match("/.*(\[attachment.*?\].*?\[\/attachment\]).*/ism", $body, $match)) { $data = BBCode::getAttachmentData($match[1]); } DI::profiler()->saveTimestamp($stamp1, 'rendering'); - if (!empty($data) && !in_array($data['url'], $ignore_links)) { - // @todo Use a template - $rendered = BBCode::convertAttachment('', BBCode::INTERNAL, false, $data); + if (isset($data['url']) && !in_array($data['url'], $ignore_links)) { + if (!empty($data['description']) || !empty($data['image']) || !empty($data['preview'])) { + $parts = parse_url($data['url']); + if (!empty($parts['scheme']) && !empty($parts['host'])) { + if (empty($data['provider_name'])) { + $data['provider_name'] = $parts['host']; + } + if (empty($data['provider_url']) || empty(parse_url($data['provider_url'], PHP_URL_SCHEME))) { + $data['provider_url'] = $parts['scheme'] . '://' . $parts['host']; + + if (!empty($parts['port'])) { + $data['provider_url'] .= ':' . $parts['port']; + } + } + } + + if (!empty($data['image'])) { + $data['image'] = Post\Link::getByLink($uriid, $data['image']); + } + + if (!empty($data['preview'])) { + $data['preview'] = Post\Link::getByLink($uriid, $data['preview']); + } + + // @todo Use a template + $rendered = BBCode::convertAttachment('', BBCode::INTERNAL, false, $data); + } elseif (!self::containsLink($content, $data['url'], Post\Media::HTML)) { + $rendered = Renderer::replaceMacros(Renderer::getMarkupTemplate('content/link.tpl'), [ + '$url' => $data['url'], + '$title' => $data['title'], + ]); + } else { + return $content; + } + if ($shared) { return str_replace(BBCode::BOTTOM_ANCHOR, BBCode::BOTTOM_ANCHOR . $rendered, $content); } else { @@ -2949,18 +3135,19 @@ class Item 'href' => "display/" . $item['guid'], 'orig' => "display/" . $item['guid'], 'title' => DI::l10n()->t('View on separate page'), - 'orig_title' => DI::l10n()->t('view on separate page'), + 'orig_title' => DI::l10n()->t('View on separate page'), ]; if (!empty($item['plink'])) { - $ret["href"] = DI::baseUrl()->remove($item['plink']); - $ret["title"] = DI::l10n()->t('link to source'); + $ret['href'] = DI::baseUrl()->remove($item['plink']); + $ret['title'] = DI::l10n()->t('Link to source'); } } elseif (!empty($item['plink']) && ($item['private'] != self::PRIVATE)) { $ret = [ 'href' => $item['plink'], 'orig' => $item['plink'], - 'title' => DI::l10n()->t('link to source'), + 'title' => DI::l10n()->t('Link to source'), + 'orig_title' => DI::l10n()->t('Link to source'), ]; } else { $ret = []; @@ -3198,4 +3385,41 @@ class Item return true; } + + /** + * Improve the data in shared posts + * + * @param array $item + * @return string body + */ + public static function improveSharedDataInBody(array $item) + { + $shared = BBCode::fetchShareAttributes($item['body']); + if (empty($shared['link'])) { + return $item['body']; + } + + $id = self::fetchByLink($shared['link']); + Logger::info('Fetched shared post', ['uri-id' => $item['uri-id'], 'id' => $id, 'author' => $shared['profile'], 'url' => $shared['link'], 'guid' => $shared['guid'], 'callstack' => System::callstack()]); + if (!$id) { + return $item['body']; + } + + $shared_item = Post::selectFirst(['author-name', 'author-link', 'author-avatar', 'plink', 'created', 'guid', 'title', 'body'], ['id' => $id]); + if (!DBA::isResult($shared_item)) { + return $item['body']; + } + + $shared_content = BBCode::getShareOpeningTag($shared_item['author-name'], $shared_item['author-link'], $shared_item['author-avatar'], $shared_item['plink'], $shared_item['created'], $shared_item['guid']); + + if (!empty($shared_item['title'])) { + $shared_content .= '[h3]'.$shared_item['title'].'[/h3]'."\n"; + } + + $shared_content .= $shared_item['body']; + + $item['body'] = preg_replace("/\[share.*?\](.*)\[\/share\]/ism", $shared_content . '[/share]', $item['body']); + Logger::info('New shared data', ['uri-id' => $item['uri-id'], 'id' => $id, 'shared_item' => $shared_item]); + return $item['body']; + } }