+ $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'));
+ $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::addNonVisualAttachments($attachments, $item, $s, false);
+
+ // Map.
+ if (strpos($s, '<div class="map">') !== false && !empty($item['coord'])) {
+ $x = Map::byCoordinates(trim($item['coord']));
+ if ($x) {
+ $s = preg_replace('/\<div class\=\"map\"\>/', '$0' . $x, $s);
+ }
+ }
+
+ // Replace friendica image url size with theme preference.
+ if (!empty($a->theme_info['item_image_size'])) {
+ $ps = $a->theme_info['item_image_size'];
+ $s = preg_replace('|(<img[^>]+src="[^"]+/photo/[0-9a-f]+)-[0-9]|', "$1-" . $ps, $s);
+ }
+
+ $s = HTML::applyContentFilter($s, $filter_reasons);
+
+ $hook_data = ['item' => $item, 'html' => $s];
+ Hook::callAll('prepare_body_final', $hook_data);
+
+ return $hook_data['html'];
+ }
+
+ /**
+ * Check if the body contains a link
+ *
+ * @param string $body
+ * @param string $url
+ * @return bool
+ */
+ public static function containsLink(string $body, string $url)
+ {
+ if (strpos($body, $url)) {
+ return true;
+ }
+ foreach ([0, 1, 2] as $size) {
+ if (preg_match('#/photo/.*-' . $size . '\.#ism', $url) &&
+ strpos(preg_replace('#(/photo/.*)-[012]\.#ism', '$1-' . $size . '.', $body), $url)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Add visual attachments to the content
+ *
+ * @param array $attachments
+ * @param array $item
+ * @param string $content
+ * @return string modified content
+ */
+ private static function addVisualAttachments(array $attachments, array $item, string $content, bool $shared)
+ {
+ $stamp1 = microtime(true);
+ $leading = '';
+ $trailing = '';
+
+ // @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'])) {
+ continue;
+ }