Merge pull request #7903 from annando/add-share-data

Add data for shared posts from the original
This commit is contained in:
Hypolite Petovan 2019-12-05 08:43:47 -05:00 committed by GitHub
commit 0f476498f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 143 additions and 214 deletions

View file

@ -2019,7 +2019,7 @@ function api_statuses_repeat($type)
Logger::log('API: api_statuses_repeat: '.$id); Logger::log('API: api_statuses_repeat: '.$id);
$fields = ['body', 'author-name', 'author-link', 'author-avatar', 'guid', 'created', 'plink']; $fields = ['body', 'title', 'attach', 'tag', 'author-name', 'author-link', 'author-avatar', 'guid', 'created', 'plink'];
$item = Item::selectFirst($fields, ['id' => $id, 'private' => false]); $item = Item::selectFirst($fields, ['id' => $id, 'private' => false]);
if (DBA::isResult($item) && $item['body'] != "") { if (DBA::isResult($item) && $item['body'] != "") {
@ -2029,10 +2029,16 @@ function api_statuses_repeat($type)
} else { } else {
$post = share_header($item['author-name'], $item['author-link'], $item['author-avatar'], $item['guid'], $item['created'], $item['plink']); $post = share_header($item['author-name'], $item['author-link'], $item['author-avatar'], $item['guid'], $item['created'], $item['plink']);
if (!empty($item['title'])) {
$post .= '[h3]' . $item['title'] . "[/h3]\n";
}
$post .= $item['body']; $post .= $item['body'];
$post .= "[/share]"; $post .= "[/share]";
} }
$_REQUEST['body'] = $post; $_REQUEST['body'] = $post;
$_REQUEST['tag'] = $item['tag'];
$_REQUEST['attach'] = $item['attach'];
$_REQUEST['profile_uid'] = api_user(); $_REQUEST['profile_uid'] = api_user();
$_REQUEST['api_source'] = true; $_REQUEST['api_source'] = true;
@ -5150,99 +5156,30 @@ function api_share_as_retweet(&$item)
} }
} }
/// @TODO "$1" should maybe mean '$1' ? $reshared = Item::getShareArray($item);
$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", "$1", $body); if (empty($reshared)) {
/*
* Skip if there is no shared message in there
* we already checked this in diaspora::isReshare()
* but better one more than one less...
*/
if (($body == $attributes) || empty($attributes)) {
return false; return false;
} }
// build the fake reshared item
$reshared_item = $item; $reshared_item = $item;
$author = ""; if (empty($reshared['shared']) || empty($reshared['profile']) || empty($reshared['author']) || empty($reshared['avatar']) || empty($reshared['posted'])) {
preg_match("/author='(.*?)'/ism", $attributes, $matches);
if (!empty($matches[1])) {
$author = html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8');
}
preg_match('/author="(.*?)"/ism', $attributes, $matches);
if (!empty($matches[1])) {
$author = $matches[1];
}
$profile = "";
preg_match("/profile='(.*?)'/ism", $attributes, $matches);
if (!empty($matches[1])) {
$profile = $matches[1];
}
preg_match('/profile="(.*?)"/ism', $attributes, $matches);
if (!empty($matches[1])) {
$profile = $matches[1];
}
$avatar = "";
preg_match("/avatar='(.*?)'/ism", $attributes, $matches);
if (!empty($matches[1])) {
$avatar = $matches[1];
}
preg_match('/avatar="(.*?)"/ism', $attributes, $matches);
if (!empty($matches[1])) {
$avatar = $matches[1];
}
$link = "";
preg_match("/link='(.*?)'/ism", $attributes, $matches);
if (!empty($matches[1])) {
$link = $matches[1];
}
preg_match('/link="(.*?)"/ism', $attributes, $matches);
if (!empty($matches[1])) {
$link = $matches[1];
}
$posted = "";
preg_match("/posted='(.*?)'/ism", $attributes, $matches);
if (!empty($matches[1])) {
$posted = $matches[1];
}
preg_match('/posted="(.*?)"/ism', $attributes, $matches);
if (!empty($matches[1])) {
$posted = $matches[1];
}
if (!preg_match("/(.*?)\[share.*?\]\s?(.*?)\s?\[\/share\]\s?(.*?)/ism", $body, $matches)) {
return false; return false;
} }
$pre_body = trim($matches[1]); if (!empty($reshared['comment'])) {
if ($pre_body != '') { $item['body'] = $reshared['comment'];
$item['body'] = $pre_body;
} }
$shared_body = trim($matches[2]); $reshared_item["share-pre-body"] = $reshared['comment'];
$reshared_item["body"] = $reshared['shared'];
if (($shared_body == "") || ($profile == "") || ($author == "") || ($avatar == "") || ($posted == "")) { $reshared_item["author-id"] = Contact::getIdForURL($reshared['profile'], 0, true);
return false; $reshared_item["author-name"] = $reshared['author'];
} $reshared_item["author-link"] = $reshared['profile'];
$reshared_item["author-avatar"] = $reshared['avatar'];
$reshared_item["share-pre-body"] = $pre_body; $reshared_item["plink"] = $reshared['link'] ?? '';
$reshared_item["body"] = $shared_body; $reshared_item["created"] = $reshared['posted'];
$reshared_item["author-id"] = Contact::getIdForURL($profile, 0, true); $reshared_item["edited"] = $reshared['posted'];
$reshared_item["author-name"] = $author;
$reshared_item["author-link"] = $profile;
$reshared_item["author-avatar"] = $avatar;
$reshared_item["plink"] = $link;
$reshared_item["created"] = $posted;
$reshared_item["edited"] = $posted;
return $reshared_item; return $reshared_item;
} }

View file

@ -133,51 +133,20 @@ function display_fetchauthor($a, $item)
$profiledata['network'] = $author['network']; $profiledata['network'] = $author['network'];
// Check for a repeated message // Check for a repeated message
$skip = false; $shared = Item::getShareArray($item);
$body = trim($item["body"]); if (!empty($shared) && empty($shared['comment'])) {
if (!empty($shared['author'])) {
// Skip if it isn't a pure repeated messages $profiledata['name'] = $shared['author'];
// Does it start with a share?
if (!$skip && strpos($body, "[share") > 0) {
$skip = true;
}
// Does it end with a share?
if (!$skip && (strlen($body) > (strrpos($body, "[/share]") + 8))) {
$skip = true;
}
if (!$skip) {
$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body);
// Skip if there is no shared message in there
if ($body == $attributes) {
$skip = true;
}
} }
if (!$skip) { if (!empty($shared['profile'])) {
preg_match("/author='(.*?)'/ism", $attributes, $matches); $profiledata['url'] = $shared['profile'];
if (!empty($matches[1])) {
$profiledata["name"] = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8');
} }
preg_match('/author="(.*?)"/ism', $attributes, $matches);
if (!empty($matches[1])) { if (!empty($shared['avatar'])) {
$profiledata["name"] = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8'); $profiledata['photo'] = $shared['avatar'];
}
preg_match("/profile='(.*?)'/ism", $attributes, $matches);
if (!empty($matches[1])) {
$profiledata["url"] = $matches[1];
}
preg_match('/profile="(.*?)"/ism', $attributes, $matches);
if (!empty($matches[1])) {
$profiledata["url"] = $matches[1];
}
preg_match("/avatar='(.*?)'/ism", $attributes, $matches);
if (!empty($matches[1])) {
$profiledata["photo"] = $matches[1];
}
preg_match('/avatar="(.*?)"/ism', $attributes, $matches);
if (!empty($matches[1])) {
$profiledata["photo"] = $matches[1];
} }
$profiledata["nickname"] = $profiledata["name"]; $profiledata["nickname"] = $profiledata["name"];
$profiledata["network"] = Protocol::matchByProfileUrl($profiledata["url"]); $profiledata["network"] = Protocol::matchByProfileUrl($profiledata["url"]);

View file

@ -730,6 +730,9 @@ function item_post(App $a) {
} }
} }
// If this was a share, add missing data here
$datarray = Item::addShareDataFromOriginal($datarray);
$post_id = Item::insert($datarray); $post_id = Item::insert($datarray);
if (!$post_id) { if (!$post_id) {

View file

@ -1055,7 +1055,7 @@ class BBCode extends BaseObject
$text = ($is_quote_share? '<br />' : '') . '<p>' . html_entity_decode('&#x2672; ', ENT_QUOTES, 'UTF-8') . ' @' . $author_contact['addr'] . ': ' . $content . '</p>' . "\n"; $text = ($is_quote_share? '<br />' : '') . '<p>' . html_entity_decode('&#x2672; ', ENT_QUOTES, 'UTF-8') . ' @' . $author_contact['addr'] . ': ' . $content . '</p>' . "\n";
break; break;
case 9: // ActivityPub case 9: // ActivityPub
$author = '@<span class="vcard"><a href="' . $author_contact['url'] . '" class="url u-url mention" title="' . $author_contact['addr'] . '"><span class="fn nickname mention">' . $author_contact['addr'] . ':</span></a></span>'; $author = '@<span class="vcard"><a href="' . $author_contact['url'] . '" class="url u-url mention" title="' . $author_contact['addr'] . '"><span class="fn nickname mention">' . $author_contact['addr'] . '</span></a>:</span>';
$text = '<div><a href="' . $attributes['link'] . '">' . html_entity_decode('&#x2672;', ENT_QUOTES, 'UTF-8') . '</a> ' . $author . '<blockquote>' . $content . '</blockquote></div>' . "\n"; $text = '<div><a href="' . $attributes['link'] . '">' . html_entity_decode('&#x2672;', ENT_QUOTES, 'UTF-8') . '</a> ' . $author . '<blockquote>' . $content . '</blockquote></div>' . "\n";
break; break;
default: default:

View file

@ -3759,4 +3759,83 @@ class Item extends BaseObject
return 0; return 0;
} }
/**
* Return share data from an item array (if the item is shared item)
* We are providing the complete Item array, because at some time in the future
* we hopefully will define these values not in the body anymore but in some item fields.
* This function is meant to replace all similar functions in the system.
*
* @param array $item
*
* @return array with share information
*/
public static function getShareArray($item)
{
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;
}
/**
* Fetch item information for shared items from the original items and adds it.
*
* @param array $item
*
* @return array item array with data from the original item
*/
public static function addShareDataFromOriginal($item)
{
$shared = self::getShareArray($item);
if (empty($shared)) {
return $item;
}
// Real reshares always have got a GUID.
if (empty($shared['guid'])) {
return $item;
}
$uid = $item['uid'] ?? 0;
// first try to fetch the item via the GUID. This will work for all reshares that had been created on this system
$shared_item = self::selectFirst(['title', 'body', 'attach'], ['guid' => $shared['guid'], 'uid' => [0, $uid]]);
if (!DBA::isResult($shared_item)) {
// Otherwhise try to find (and possibly fetch) the item via the link. This should work for Diaspora and ActivityPub posts
$id = self::fetchByLink($shared['link'], $uid);
if (empty($id)) {
Logger::info('Original item not found', ['url' => $shared['link'], 'callstack' => System::callstack()]);
return $item;
}
$shared_item = self::selectFirst(['title', 'body', 'attach'], ['id' => $id]);
if (!DBA::isResult($shared_item)) {
return $item;
}
Logger::info('Got shared data from url', ['url' => $shared['link'], 'callstack' => System::callstack()]);
} else {
Logger::info('Got shared data from guid', ['guid' => $shared['guid'], 'callstack' => System::callstack()]);
}
if (!empty($shared_item['title'])) {
$body = '[h3]' . $shared_item['title'] . "[/h3]\n" . $shared_item['body'];
unset($shared_item['title']);
} else {
$body = $shared_item['body'];
}
$item['body'] = preg_replace("/(.*?\[share.*?\]\s?).*?(\s?\[\/share\]\s?)/ism", '$1' . $body . '$2', $item['body']);
unset($shared_item['body']);
return array_merge($item, $shared_item);
}
} }

View file

@ -1401,23 +1401,12 @@ class Transmitter
*/ */
public static function getAnnounceArray($item) public static function getAnnounceArray($item)
{ {
if (!preg_match("/(.*?)\[share(.*?)\]\s?.*?\s?\[\/share\]\s?/ism", $item['body'], $matches)) { $reshared = Item::getShareArray($item);
if (empty($reshared['guid'])) {
return []; return [];
} }
$attributes = $matches[2]; $reshared_item = Item::selectFirst([], ['guid' => $reshared['guid']]);
$comment = $matches[1];
preg_match("/guid='(.*?)'/ism", $attributes, $matches);
if (empty($matches[1])) {
preg_match('/guid="(.*?)"/ism', $attributes, $matches);
}
if (empty($matches[1])) {
return [];
}
$reshared_item = Item::selectFirst([], ['guid' => $matches[1]]);
if (!DBA::isResult($reshared_item)) { if (!DBA::isResult($reshared_item)) {
return []; return [];
} }
@ -1431,7 +1420,7 @@ class Transmitter
return []; return [];
} }
return ['object' => $reshared_item, 'actor' => $profile, 'comment' => trim($comment)]; return ['object' => $reshared_item, 'actor' => $profile, 'comment' => $reshared['comment']];
} }
/** /**

View file

@ -2537,6 +2537,9 @@ class DFRN
} }
} }
// Ensure to have the correct share data
$item = Item::addShareDataFromOriginal($item);
if ($entrytype == DFRN::REPLY_RC) { if ($entrytype == DFRN::REPLY_RC) {
$item["wall"] = 1; $item["wall"] = 1;
} elseif ($entrytype == DFRN::TOP_LEVEL) { } elseif ($entrytype == DFRN::TOP_LEVEL) {

View file

@ -2523,7 +2523,7 @@ class Diaspora
} }
// Do we already have this item? // Do we already have this item?
$fields = ['body', 'tag', 'app', 'created', 'object-type', 'uri', 'guid', $fields = ['body', 'title', 'attach', 'tag', 'app', 'created', 'object-type', 'uri', 'guid',
'author-name', 'author-link', 'author-avatar']; 'author-name', 'author-link', 'author-avatar'];
$condition = ['guid' => $guid, 'visible' => true, 'deleted' => false, 'private' => false]; $condition = ['guid' => $guid, 'visible' => true, 'deleted' => false, 'private' => false];
$item = Item::selectFirst($fields, $condition); $item = Item::selectFirst($fields, $condition);
@ -2701,9 +2701,15 @@ class Diaspora
$original_item["created"], $original_item["created"],
$orig_url $orig_url
); );
if (!empty($original_item['title'])) {
$prefix .= '[h3]' . $original_item['title'] . "[/h3]\n";
}
$datarray["body"] = $prefix.$original_item["body"]."[/share]"; $datarray["body"] = $prefix.$original_item["body"]."[/share]";
$datarray["tag"] = $original_item["tag"]; $datarray["tag"] = $original_item["tag"];
$datarray["attach"] = $original_item["attach"];
$datarray["app"] = $original_item["app"]; $datarray["app"] = $original_item["app"];
$datarray["plink"] = self::plink($author, $guid); $datarray["plink"] = self::plink($author, $guid);
@ -3385,69 +3391,37 @@ class Diaspora
{ {
$body = trim($body); $body = trim($body);
$reshared = Item::getShareArray(['body' => $body]);
if (empty($reshared)) {
return false;
}
// Skip if it isn't a pure repeated messages // Skip if it isn't a pure repeated messages
// Does it start with a share? // Does it start with a share?
if ((strpos($body, "[share") > 0) && $complete) { if (!empty($reshared['comment']) && $complete) {
return false; return false;
} }
// Does it end with a share? if (!empty($reshared['guid']) && $complete) {
if (strlen($body) > (strrpos($body, "[/share]") + 8)) { $condition = ['guid' => $reshared['guid'], 'network' => [Protocol::DFRN, Protocol::DIASPORA]];
return false;
}
$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", "$1", $body);
// Skip if there is no shared message in there
if ($body == $attributes) {
return false;
}
// If we don't do the complete check we quit here
$guid = "";
preg_match("/guid='(.*?)'/ism", $attributes, $matches);
if (!empty($matches[1])) {
$guid = $matches[1];
}
preg_match('/guid="(.*?)"/ism', $attributes, $matches);
if (!empty($matches[1])) {
$guid = $matches[1];
}
if (($guid != "") && $complete) {
$condition = ['guid' => $guid, 'network' => [Protocol::DFRN, Protocol::DIASPORA]];
$item = Item::selectFirst(['contact-id'], $condition); $item = Item::selectFirst(['contact-id'], $condition);
if (DBA::isResult($item)) { if (DBA::isResult($item)) {
$ret = []; $ret = [];
$ret["root_handle"] = self::handleFromContact($item["contact-id"]); $ret["root_handle"] = self::handleFromContact($item["contact-id"]);
$ret["root_guid"] = $guid; $ret["root_guid"] = $reshared['guid'];
return $ret; return $ret;
} elseif ($complete) { } elseif ($complete) {
// We are resharing something that isn't a DFRN or Diaspora post. // 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. // So we have to return "false" on "$complete" to not trigger a reshare.
return false; return false;
} }
} elseif (($guid == "") && $complete) { } elseif (empty($reshared['guid']) && $complete) {
return false; return false;
} }
$ret["root_guid"] = $guid;
$profile = "";
preg_match("/profile='(.*?)'/ism", $attributes, $matches);
if (!empty($matches[1])) {
$profile = $matches[1];
}
preg_match('/profile="(.*?)"/ism', $attributes, $matches);
if (!empty($matches[1])) {
$profile = $matches[1];
}
$ret = []; $ret = [];
if (!empty($profile) && ($cid = Contact::getIdForURL($profile))) { if (!empty($reshared['profile']) && ($cid = Contact::getIdForURL($reshared['profile']))) {
$contact = DBA::selectFirst('contact', ['addr'], ['id' => $cid]); $contact = DBA::selectFirst('contact', ['addr'], ['id' => $cid]);
if (!empty($contact['addr'])) { if (!empty($contact['addr'])) {
$ret['root_handle'] = $contact['addr']; $ret['root_handle'] = $contact['addr'];

View file

@ -1199,37 +1199,12 @@ class OStatus
*/ */
private static function getResharedGuid(array $item) private static function getResharedGuid(array $item)
{ {
$body = trim($item["body"]); $reshared = Item::getShareArray($item);
if (empty($reshared['guid']) || !empty($reshared['comment'])) {
// Skip if it isn't a pure repeated messages return '';
// Does it start with a share?
if (strpos($body, "[share") > 0) {
return "";
} }
// Does it end with a share? return $reshared['guid'];
if (strlen($body) > (strrpos($body, "[/share]") + 8)) {
return "";
}
$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", "$1", $body);
// Skip if there is no shared message in there
if ($body == $attributes) {
return false;
}
$guid = "";
preg_match("/guid='(.*?)'/ism", $attributes, $matches);
if (!empty($matches[1])) {
$guid = $matches[1];
}
preg_match('/guid="(.*?)"/ism', $attributes, $matches);
if (!empty($matches[1])) {
$guid = $matches[1];
}
return $guid;
} }
/** /**