From a7d49877a87dbf409766fafedee488cd4317b255 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sat, 25 Jun 2022 06:15:26 -0400 Subject: [PATCH] Centralize share tag attribute extraction code in Content\Text\BBCode --- src/Content/Text/BBCode.php | 53 ++++++++++++++++++++++++------------- src/Model/Item.php | 13 +-------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index c3e255a4d..f43c40d31 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -995,29 +995,51 @@ class BBCode } /** - * - * @param string $text A BBCode string - * @return array share attributes + * @param string $text A BBCode string + * @return array Empty array if no share tag is present or the following array, missing attributes end up empty strings: + * - comment: Text before the opening share tag + * - shared : Text inside the share tags + * - author : (Optional) Display name of the shared author + * - profile: (Optional) Profile page URL of the shared author + * - avatar : (Optional) Profile picture URL of the shared author + * - link : (Optional) Canonical URL of the shared post + * - posted : (Optional) Date the shared post was initially posted ("Y-m-d H:i:s" in GMT) + * - guid : (Optional) Shared post GUID if any */ - public static function fetchShareAttributes($text) + public static function fetchShareAttributes(string $text): array { DI::profiler()->startRecording('rendering'); // See Issue https://github.com/friendica/friendica/issues/10454 // Hashtags in usernames are expanded to links. This here is a quick fix. - $text = preg_replace('/([@!#])\[url\=.*?\](.*?)\[\/url\]/ism', '$1$2', $text); + $text = preg_replace('~([@!#])\[url=.*?](.*?)\[/url]~ism', '$1$2', $text); - $attributes = []; - if (!preg_match("/(.*?)\[share(.*?)\](.*)\[\/share\]/ism", $text, $matches)) { + if (!preg_match('~(.*?)\[share(.*?)](.*)\[/share]~ism', $text, $matches)) { DI::profiler()->stopRecording(); - return $attributes; + return []; } - $attribute_string = $matches[2]; + $attributes = self::extractShareAttributes($matches[2]); + + $attributes['comment'] = trim($matches[1]); + $attributes['shared'] = trim($matches[3]); + + DI::profiler()->stopRecording(); + return $attributes; + } + + /** + * @see BBCode::fetchShareAttributes() + * @param string $shareString Internal opening share tag string matched by the regular expression + * @return array A fixed attribute array where missing attribute are represented by empty strings + */ + private static function extractShareAttributes(string $shareString): array + { + $attributes = []; foreach (['author', 'profile', 'avatar', 'link', 'posted', 'guid'] as $field) { - preg_match("/$field=(['\"])(.+?)\\1/ism", $attribute_string, $matches); + preg_match("/$field=(['\"])(.+?)\\1/ism", $shareString, $matches); $attributes[$field] = html_entity_decode($matches[2] ?? '', ENT_QUOTES, 'UTF-8'); } - DI::profiler()->stopRecording(); + return $attributes; } @@ -1044,14 +1066,9 @@ class BBCode { DI::profiler()->startRecording('rendering'); $return = preg_replace_callback( - "/(.*?)\[share(.*?)\](.*)\[\/share\]/ism", + '~(.*?)\[share(.*?)](.*)\[/share]~ism', function ($match) use ($callback, $uriid) { - $attribute_string = $match[2]; - $attributes = []; - foreach (['author', 'profile', 'avatar', 'link', 'posted', 'guid'] as $field) { - preg_match("/$field=(['\"])(.+?)\\1/ism", $attribute_string, $matches); - $attributes[$field] = html_entity_decode($matches[2] ?? '', ENT_QUOTES, 'UTF-8'); - } + $attributes = self::extractShareAttributes($match[2]); $author_contact = Contact::getByURL($attributes['profile'], false, ['id', 'url', 'addr', 'name', 'micro']); $author_contact['url'] = ($author_contact['url'] ?? $attributes['profile']); diff --git a/src/Model/Item.php b/src/Model/Item.php index bb8080e5f..4013dc2ce 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -3438,18 +3438,7 @@ class Item */ public static function getShareArray(array $item): array { - if (!preg_match("/(.*?)\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", $item['body'], $matches)) { - return []; - } - - $attribute_string = $matches[2]; - $attributes = ['comment' => trim($matches[1]), 'shared' => trim($matches[3])]; - foreach (['author', 'profile', 'avatar', 'guid', 'posted', 'link'] as $field) { - if (preg_match("/$field=(['\"])(.+?)\\1/ism", $attribute_string, $matches)) { - $attributes[$field] = trim(html_entity_decode($matches[2] ?? '', ENT_QUOTES, 'UTF-8')); - } - } - return $attributes; + return BBCode::fetchShareAttributes($item['body']); } /**