Merge pull request #11688 from MrPetovan/bug/11635-mod-photos-posted

Replace obsolete posted sort field by created in mod\photos
This commit is contained in:
Philipp 2022-06-25 17:54:49 +02:00 committed by GitHub
commit 9527cd5cb3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 169 additions and 37 deletions

View file

@ -977,7 +977,7 @@ function photos_content(App $a)
/// @TODO I have seen this many times, maybe generalize it script-wide and encapsulate it? /// @TODO I have seen this many times, maybe generalize it script-wide and encapsulate it?
$order_field = $_GET['order'] ?? ''; $order_field = $_GET['order'] ?? '';
if ($order_field === 'posted') { if ($order_field === 'created') {
$order = 'ASC'; $order = 'ASC';
} else { } else {
$order = 'DESC'; $order = 'DESC';
@ -1031,10 +1031,10 @@ function photos_content(App $a)
$drop = [DI::l10n()->t('Drop Album'), 'photos/' . $user['nickname'] . '/album/' . bin2hex($album) . '/drop']; $drop = [DI::l10n()->t('Drop Album'), 'photos/' . $user['nickname'] . '/album/' . bin2hex($album) . '/drop'];
} }
if ($order_field === 'posted') { if ($order_field === 'created') {
$order = [DI::l10n()->t('Show Newest First'), 'photos/' . $user['nickname'] . '/album/' . bin2hex($album), 'oldest']; $order = [DI::l10n()->t('Show Newest First'), 'photos/' . $user['nickname'] . '/album/' . bin2hex($album), 'oldest'];
} else { } else {
$order = [DI::l10n()->t('Show Oldest First'), 'photos/' . $user['nickname'] . '/album/' . bin2hex($album) . '?order=posted', 'newest']; $order = [DI::l10n()->t('Show Oldest First'), 'photos/' . $user['nickname'] . '/album/' . bin2hex($album) . '?order=created', 'newest'];
} }
$photos = []; $photos = [];
@ -1054,7 +1054,7 @@ function photos_content(App $a)
'id' => $rr['id'], 'id' => $rr['id'],
'twist' => ' ' . ($twist ? 'rotleft' : 'rotright') . rand(2,4), 'twist' => ' ' . ($twist ? 'rotleft' : 'rotright') . rand(2,4),
'link' => 'photos/' . $user['nickname'] . '/image/' . $rr['resource-id'] 'link' => 'photos/' . $user['nickname'] . '/image/' . $rr['resource-id']
. ($order_field === 'posted' ? '?order=posted' : ''), . ($order_field === 'created' ? '?order=created' : ''),
'title' => DI::l10n()->t('View Photo'), 'title' => DI::l10n()->t('View Photo'),
'src' => 'photo/' . $rr['resource-id'] . '-' . $rr['scale'] . '.' .$ext, 'src' => 'photo/' . $rr['resource-id'] . '-' . $rr['scale'] . '.' .$ext,
'alt' => $imgalt_e, 'alt' => $imgalt_e,
@ -1122,7 +1122,7 @@ function photos_content(App $a)
if ($cmd === 'view' && !DI::config()->get('system', 'no_count', false)) { if ($cmd === 'view' && !DI::config()->get('system', 'no_count', false)) {
$order_field = $_GET['order'] ?? ''; $order_field = $_GET['order'] ?? '';
if ($order_field === 'posted') { if ($order_field === 'created') {
$params = ['order' => [$order_field]]; $params = ['order' => [$order_field]];
} elseif (!empty($order_field)) { } elseif (!empty($order_field)) {
$params = ['order' => [$order_field => true]]; $params = ['order' => [$order_field => true]];
@ -1150,10 +1150,10 @@ function photos_content(App $a)
} }
if (!is_null($prv)) { if (!is_null($prv)) {
$prevlink = 'photos/' . $user['nickname'] . '/image/' . $prvnxt[$prv]['resource-id'] . ($order_field === 'posted' ? '?order=posted' : ''); $prevlink = 'photos/' . $user['nickname'] . '/image/' . $prvnxt[$prv]['resource-id'] . ($order_field === 'created' ? '?order=created' : '');
} }
if (!is_null($nxt)) { if (!is_null($nxt)) {
$nextlink = 'photos/' . $user['nickname'] . '/image/' . $prvnxt[$nxt]['resource-id'] . ($order_field === 'posted' ? '?order=posted' : ''); $nextlink = 'photos/' . $user['nickname'] . '/image/' . $prvnxt[$nxt]['resource-id'] . ($order_field === 'created' ? '?order=created' : '');
} }
$tpl = Renderer::getMarkupTemplate('photo_edit_head.tpl'); $tpl = Renderer::getMarkupTemplate('photo_edit_head.tpl');

View file

@ -995,29 +995,51 @@ class BBCode
} }
/** /**
* * @param string $text A BBCode string
* @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:
* @return array share attributes * - 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'); DI::profiler()->startRecording('rendering');
// See Issue https://github.com/friendica/friendica/issues/10454 // See Issue https://github.com/friendica/friendica/issues/10454
// Hashtags in usernames are expanded to links. This here is a quick fix. // 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(); 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) { 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'); $attributes[$field] = html_entity_decode($matches[2] ?? '', ENT_QUOTES, 'UTF-8');
} }
DI::profiler()->stopRecording();
return $attributes; return $attributes;
} }
@ -1044,14 +1066,9 @@ class BBCode
{ {
DI::profiler()->startRecording('rendering'); DI::profiler()->startRecording('rendering');
$return = preg_replace_callback( $return = preg_replace_callback(
"/(.*?)\[share(.*?)\](.*)\[\/share\]/ism", '~(.*?)\[share(.*?)](.*)\[/share]~ism',
function ($match) use ($callback, $uriid) { function ($match) use ($callback, $uriid) {
$attribute_string = $match[2]; $attributes = self::extractShareAttributes($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');
}
$author_contact = Contact::getByURL($attributes['profile'], false, ['id', 'url', 'addr', 'name', 'micro']); $author_contact = Contact::getByURL($attributes['profile'], false, ['id', 'url', 'addr', 'name', 'micro']);
$author_contact['url'] = ($author_contact['url'] ?? $attributes['profile']); $author_contact['url'] = ($author_contact['url'] ?? $attributes['profile']);

View file

@ -3438,18 +3438,7 @@ class Item
*/ */
public static function getShareArray(array $item): array public static function getShareArray(array $item): array
{ {
if (!preg_match("/(.*?)\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", $item['body'], $matches)) { return BBCode::fetchShareAttributes($item['body']);
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;
} }
/** /**

View file

@ -467,4 +467,130 @@ Karl Marx - Die ursprüngliche Akkumulation
self::assertEquals($expected, $actual); self::assertEquals($expected, $actual);
} }
public function dataFetchShareAttributes(): array
{
return [
'no-tag' => [
'expected' => [],
'text' => 'Venture the only home we\'ve ever known laws of physics tendrils of gossamer clouds a still more glorious dawn awaits Sea of Tranquility. With pretty stories for which there\'s little good evidence the ash of stellar alchemy corpus callosum preserve and cherish that pale blue dot descended from astronomers preserve and cherish that pale blue dot. A mote of dust suspended in a sunbeam paroxysm of global death two ghostly white figures in coveralls and helmets are softly dancing descended from astronomers star stuff harvesting star light gathered by gravity and billions upon billions upon billions upon billions upon billions upon billions upon billions.',
],
'just-open' => [
'expected' => [],
'text' => '[share]',
],
'empty-tag' => [
'expected' => [
'author' => '',
'profile' => '',
'avatar' => '',
'link' => '',
'posted' => '',
'guid' => '',
'comment' => '',
'shared' => '',
],
'text' => '[share][/share]',
],
'comment-shared' => [
'expected' => [
'author' => '',
'profile' => '',
'avatar' => '',
'link' => '',
'posted' => '',
'guid' => '',
'comment' => 'comment',
'shared' => 'shared',
],
'text' => ' comment
[share]
shared
[/share]',
],
'all-attributes' => [
'expected' => [
'author' => 'Hypolite Petovan',
'profile' => 'https://friendica.mrpetovan.com/profile/hypolite',
'avatar' => 'https://friendica.mrpetovan.com/photo/20682437145daa4e85f019a278584494-5.png',
'link' => 'https://friendica.mrpetovan.com/display/735a2029-1062-ab23-42e4-f9c631220243',
'posted' => '2022-06-16 12:34:10',
'guid' => '735a2029-1062-ab23-42e4-f9c631220243',
'comment' => '',
'shared' => 'George Lucas: I made a science-fiction universe with a straightforward anti-authoritarianism plot where even the libertarian joins the rebellion.
Disney: So a morally grey “choose your side” story, right?
Lucas: For the right price, yes.',
],
'text' => "[share
author='Hypolite Petovan'
profile='https://friendica.mrpetovan.com/profile/hypolite'
avatar='https://friendica.mrpetovan.com/photo/20682437145daa4e85f019a278584494-5.png'
link='https://friendica.mrpetovan.com/display/735a2029-1062-ab23-42e4-f9c631220243'
posted='2022-06-16 12:34:10'
guid='735a2029-1062-ab23-42e4-f9c631220243'
]George Lucas: I made a science-fiction universe with a straightforward anti-authoritarianism plot where even the libertarian joins the rebellion.
Disney: So a morally grey “choose your side” story, right?
Lucas: For the right price, yes.[/share]",
],
'optional-attributes' => [
'expected' => [
'author' => 'Hypolite Petovan',
'profile' => 'https://friendica.mrpetovan.com/profile/hypolite',
'avatar' => 'https://friendica.mrpetovan.com/photo/20682437145daa4e85f019a278584494-5.png',
'link' => 'https://friendica.mrpetovan.com/display/735a2029-1062-ab23-42e4-f9c631220243',
'posted' => '2022-06-16 12:34:10',
'guid' => '',
'comment' => '',
'shared' => 'George Lucas: I made a science-fiction universe with a straightforward anti-authoritarianism plot where even the libertarian joins the rebellion.
Disney: So a morally grey “choose your side” story, right?
Lucas: For the right price, yes.',
],
'text' => "[share
author='Hypolite Petovan'
profile='https://friendica.mrpetovan.com/profile/hypolite'
avatar='https://friendica.mrpetovan.com/photo/20682437145daa4e85f019a278584494-5.png'
link='https://friendica.mrpetovan.com/display/735a2029-1062-ab23-42e4-f9c631220243'
posted='2022-06-16 12:34:10'
]George Lucas: I made a science-fiction universe with a straightforward anti-authoritarianism plot where even the libertarian joins the rebellion.
Disney: So a morally grey “choose your side” story, right?
Lucas: For the right price, yes.[/share]",
],
'double-quotes' => [
'expected' => [
'author' => 'Hypolite Petovan',
'profile' => 'https://friendica.mrpetovan.com/profile/hypolite',
'avatar' => 'https://friendica.mrpetovan.com/photo/20682437145daa4e85f019a278584494-5.png',
'link' => 'https://friendica.mrpetovan.com/display/735a2029-1062-ab23-42e4-f9c631220243',
'posted' => '2022-06-16 12:34:10',
'guid' => '',
'comment' => '',
'shared' => 'George Lucas: I made a science-fiction universe with a straightforward anti-authoritarianism plot where even the libertarian joins the rebellion.
Disney: So a morally grey “choose your side” story, right?
Lucas: For the right price, yes.',
],
'text' => '[share
author="Hypolite Petovan"
profile="https://friendica.mrpetovan.com/profile/hypolite"
avatar="https://friendica.mrpetovan.com/photo/20682437145daa4e85f019a278584494-5.png"
link="https://friendica.mrpetovan.com/display/735a2029-1062-ab23-42e4-f9c631220243"
posted="2022-06-16 12:34:10"
]George Lucas: I made a science-fiction universe with a straightforward anti-authoritarianism plot where even the libertarian joins the rebellion.
Disney: So a morally grey “choose your side” story, right?
Lucas: For the right price, yes.[/share]',
],
];
}
/**
* @dataProvider dataFetchShareAttributes
*
* @param array $expected Expected attribute array
* @param string $text Input text
*/
public function testFetchShareAttributes(array $expected, string $text)
{
$actual = BBCode::fetchShareAttributes($text);
self::assertEquals($expected, $actual);
}
} }