From 2de7034e166d88f8f6dc527c1b0a380a4eb49c86 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 15 Mar 2025 05:35:55 +0000 Subject: [PATCH 1/6] Improved support for backfilled posts --- src/Model/Item.php | 4 ++-- src/Model/ItemHelper.php | 20 ++++++++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/Model/Item.php b/src/Model/Item.php index 31f8a8e22e..247bd06435 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1090,9 +1090,9 @@ class Item } if ($update_commented) { - $fields = ['commented' => DateTimeFormat::utcNow(), 'changed' => DateTimeFormat::utcNow()]; + $fields = ['commented' => $posted_item['received'], 'changed' => $posted_item['received']]; } else { - $fields = ['changed' => DateTimeFormat::utcNow()]; + $fields = ['changed' => $posted_item['received']]; } Post::update($fields, ['uri-id' => $posted_item['parent-uri-id'], 'uid' => $posted_item['uid']]); diff --git a/src/Model/ItemHelper.php b/src/Model/ItemHelper.php index 9b585fd544..102b0fecba 100644 --- a/src/Model/ItemHelper.php +++ b/src/Model/ItemHelper.php @@ -205,13 +205,25 @@ final class ItemHelper $item['file'] = trim($item['file'] ?? ''); // Items cannot be stored before they happen ... - if ($item['created'] > DateTimeFormat::utcNow()) { - $item['created'] = DateTimeFormat::utcNow(); + if ($item['received'] > DateTimeFormat::utcNow()) { + $item['received'] = DateTimeFormat::utcNow(); + } + + if ($item['created'] > $item['received']) { + $item['created'] = $item['received']; } // We haven't invented time travel by now. - if ($item['edited'] > DateTimeFormat::utcNow()) { - $item['edited'] = DateTimeFormat::utcNow(); + if ($item['edited'] > $item['received'] ) { + $item['edited'] = $item['received'] ; + } + + if ($item['changed'] > $item['received'] ) { + $item['changed'] = $item['received'] ; + } + + if ($item['commented'] > $item['received'] ) { + $item['commented'] = $item['received'] ; } $item['plink'] = ($item['plink'] ?? '') ?: $this->baseUrl . '/display/' . urlencode($item['guid']); From fcb8892e2fa4055ed4ed3404881bfac8faa554ef Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 18 Mar 2025 05:33:01 +0000 Subject: [PATCH 2/6] Add missing public contacts and account-user entries --- src/Worker/Cron.php | 3 +++ src/Worker/FixContacts.php | 51 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/Worker/FixContacts.php diff --git a/src/Worker/Cron.php b/src/Worker/Cron.php index b576f09ae7..cf0529c8b4 100644 --- a/src/Worker/Cron.php +++ b/src/Worker/Cron.php @@ -121,6 +121,9 @@ class Cron Worker::add(Worker::PRIORITY_LOW, 'UpdateAllSuggestions'); + // add missing public contacts and account-user entries + Worker::add(Worker::PRIORITY_LOW, 'FixContacts'); + if (DI::config()->get('system', 'optimize_tables')) { Worker::add(Worker::PRIORITY_LOW, 'OptimizeTables'); } diff --git a/src/Worker/FixContacts.php b/src/Worker/FixContacts.php new file mode 100644 index 0000000000..2961962bc8 --- /dev/null +++ b/src/Worker/FixContacts.php @@ -0,0 +1,51 @@ +info('Add missing public contacts'); + $contacts = DBA::p("SELECT `contact`.`id` FROM `contact` LEFT JOIN `contact` AS `pcontact` ON `contact`.`uri-id` = `pcontact`.`uri-id` WHERE `pcontact`.`id` IS NULL"); + while ($contact = DBA::fetch($contacts)) { + Contact::selectAccountUserById($contact['id'], ['id']); + $added++; + } + DBA::close($contacts); + + if ($added == 0) { + DI::logger()->info('No public contacts have been added'); + } else { + DI::logger()->info('Missing public contacts have been added', ['added' => $added]); + } + + $added = 0; + DI::logger()->info('Add missing account-user entries'); + $contacts = DBA::p("SELECT `contact`.`id`, `contact`.`uid`, `contact`.`uri-id`, `contact`.`url` FROM `contact` LEFT JOIN `account-user` ON `contact`.`id` = `account-user`.`id` WHERE `contact`.`id` > ? AND `account-user`.`id` IS NULL", 0); + while ($contact = DBA::fetch($contacts)) { + Contact::setAccountUser($contact['id'], $contact['uid'], $contact['uri-id'], $contact['url']); + $added++; + } + DBA::close($contacts); + + if ($added == 0) { + DI::logger()->info('No account-user entries have been added'); + } else { + DI::logger()->info('Missing account-user entries have been added', ['added' => $added]); + } + } +} From 6f159e69bea42f1c018c21821cebe67520ad2afc Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Wed, 12 Mar 2025 22:46:36 -0400 Subject: [PATCH 3/6] Add support for more datetime formats - Unix Timestamp - RFC 3339 extended + timezone name in square brackets - Address https://github.com/friendica/friendica/issues/14647#issuecomment-2719430131 --- src/Util/DateTimeFormat.php | 6 +- tests/src/Util/DateTimeFormatTest.php | 81 +++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/Util/DateTimeFormat.php b/src/Util/DateTimeFormat.php index 42b49cbf7d..830b50a2fe 100644 --- a/src/Util/DateTimeFormat.php +++ b/src/Util/DateTimeFormat.php @@ -117,7 +117,7 @@ class DateTimeFormat $tz_to = 'UTC'; } - if (($s === '') || (!is_string($s))) { + if ($s === '') { $s = 'now'; } @@ -135,7 +135,8 @@ class DateTimeFormat } try { - $d = new DateTime($s, $from_obj); + $d = DateTime::createFromFormat('U', $s, $from_obj) + ?: new DateTime($s, $from_obj); } catch (Exception $e) { try { $d = new DateTime(self::fix($s), $from_obj); @@ -176,6 +177,7 @@ class DateTimeFormat $pregPatterns = [ ['#(\w+), (\d+ \w+ \d+) (\d+:\d+:\d+) (.+)#', '$2 $3 $4'], ['#(\d+:\d+) (\w+), (\w+) (\d+), (\d+)#', '$1 $2 $3 $4 $5'], + ['#\[[^\]]*\]#', ''], // 2025-03-07T08:54:14.341+01:00[Europe/Berlin] ]; foreach ($pregPatterns as $pattern) { diff --git a/tests/src/Util/DateTimeFormatTest.php b/tests/src/Util/DateTimeFormatTest.php index 9137659ba8..186741a67c 100644 --- a/tests/src/Util/DateTimeFormatTest.php +++ b/tests/src/Util/DateTimeFormatTest.php @@ -125,6 +125,10 @@ class DateTimeFormatTest extends MockedTestCase 'expectedDate' => '2023-04-02T17:22:42+05:30', 'dateString' => '2023-04-02\T17:22:42+05:30' ], + '2025-03-07T08:54:14.341+01:00[Europe/Berlin]' => [ + 'expectedDate' => '2025-03-07T08:54:14+01:00', + 'dateString' => '2025-03-07T08:54:14.341+01:00[Europe/Berlin]' + ], ]; } @@ -156,4 +160,81 @@ class DateTimeFormatTest extends MockedTestCase $this->assertEquals(259200, $now - $date); } + + public function dataConvert() { + return [ + 'unix timestamp' => [ + 'expected' => '2025-03-12 16:18:27', + 's' => '1741796307', + ], + 'ATOM' => [ + 'expected' => '2022-06-02 15:58:35', + 's' => '2022-06-02T16:58:35+01:00', + ], + 'COOKIE' => [ + 'expected' => '2022-06-02 14:58:35', + 's' => 'Thursday, 02-Jun-2022 16:58:35 Africa/Cairo', + ], + 'ISO 8601/RFC 3339' => [ + 'expected' => '2022-06-02 13:58:35', + 's' => '2022-06-02T16:58:35+0300', + ], + 'RFC 822/RFC 1036' => [ + 'expected' => '2022-06-02 12:58:35', + 's' => 'Thu, 02 Jun 22 16:58:35 +0400', + ], + 'RFC 850' => [ + 'expected' => '2022-06-02 11:58:35', + 's' => 'Thursday, 02-Jun-22 16:58:35 Indian/Kerguelen', + ], + 'RFC 1123/RFC 2822/RSS' => [ + 'expected' => '2022-06-02 10:58:35', + 's' => 'Thu, 02 Jun 2022 16:58:35 +0600', + ], + 'RFC 3339/W3C' => [ + 'expected' => '2025-03-07 01:54:14', + 's' => '2025-03-07T08:54:14+07:00', + ], + 'RFC 3339 extended' => [ + 'expected' => '2025-03-07 00:54:14', + 's' => '2025-03-07T08:54:14.341+08:00', + ], + 'RFC 7231' => [ + 'expected' => '2022-06-02 07:58:35', + 's' => 'Thu, 02 Jun 2022 16:58:35 Asia/Tokyo', + ], + ]; + } + + /** + * @dataProvider dataConvert + */ + public function testConvert($expected, string $s = 'now', string $tz_to = 'UTC', string $tz_from = 'UTC', string $format = DateTimeFormat::MYSQL) + { + $this->assertSame($expected, DateTimeFormat::convert($s, $tz_to, $tz_from, $format)); + } + + public function dataConvertNow() + { + return [ + 'now missing' => [ + ], + 'now empty' => [ + 's' => '', + ], + 'now now' => [ + 's' => 'now', + ], + ]; + } + + /** + * @dataProvider dataConvertNow + */ + public function testConvertNow(string $s = 'now', string $tz_to = 'UTC', string $tz_from = 'UTC', string $format = DateTimeFormat::MYSQL) + { + $this->assertSame(date(DateTimeFormat::MYSQL), DateTimeFormat::convert($s, $tz_to, $tz_from, $format)); + } + + } From 47e4bad15199f744150365f25db644e4c4795b24 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 18 Mar 2025 19:07:25 -0400 Subject: [PATCH 4/6] Fix formatting in DateTimeFormatTest --- tests/src/Util/DateTimeFormatTest.php | 69 ++++++++++++++------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/tests/src/Util/DateTimeFormatTest.php b/tests/src/Util/DateTimeFormatTest.php index 186741a67c..6cc506807e 100644 --- a/tests/src/Util/DateTimeFormatTest.php +++ b/tests/src/Util/DateTimeFormatTest.php @@ -16,39 +16,39 @@ class DateTimeFormatTest extends MockedTestCase { return [ 'validNormal' => [ - 'input' => '1990-10', + 'input' => '1990-10', 'assert' => true, ], 'validOneCharMonth' => [ - 'input' => '1990-1', + 'input' => '1990-1', 'assert' => true, ], 'validTwoCharMonth' => [ - 'input' => '1990-01', + 'input' => '1990-01', 'assert' => true, ], 'invalidFormat' => [ - 'input' => '199-11', + 'input' => '199-11', 'assert' => false, ], 'invalidFormat2' => [ - 'input' => '1990-15', + 'input' => '1990-15', 'assert' => false, ], 'invalidFormat3' => [ - 'input' => '99-101', + 'input' => '99-101', 'assert' => false, ], 'invalidFormat4' => [ - 'input' => '11-1990', + 'input' => '11-1990', 'assert' => false, ], 'invalidFuture' => [ - 'input' => '3030-12', + 'input' => '3030-12', 'assert' => false, ], 'invalidYear' => [ - 'input' => '-100-10', + 'input' => '-100-10', 'assert' => false, ], ]; @@ -79,55 +79,55 @@ class DateTimeFormatTest extends MockedTestCase return [ 'Mo, 19 Sep 2022 14:51:00 +0200' => [ 'expectedDate' => '2022-09-19T14:51:00+02:00', - 'dateString' => 'Mo, 19 Sep 2022 14:51:00 +0200', + 'dateString' => 'Mo, 19 Sep 2022 14:51:00 +0200', ], '2020-11-21T12:00:13.745339ZZ' => [ 'expectedDate' => '2020-11-21T12:00:13+00:00', - 'dateString' => '2020-11-21T12:00:13.745339ZZ', + 'dateString' => '2020-11-21T12:00:13.745339ZZ', ], '2016-09-09T13:32:00ZZ' => [ 'expectedDate' => '2016-09-09T13:32:00+00:00', - 'dateString' => '2016-09-09T13:32:00ZZ', + 'dateString' => '2016-09-09T13:32:00ZZ', ], 'Sun, 10/03/2021 - 12:41' => [ 'expectedDate' => '2021-10-03T12:41:00+00:00', - 'dateString' => 'Sun, 10/03/2021 - 12:41', + 'dateString' => 'Sun, 10/03/2021 - 12:41', ], '4:30 PM, Sep 13, 2022' => [ 'expectedDate' => '2022-09-13T16:30:00+00:00', - 'dateString' => '4:30 PM, Sep 13, 2022', + 'dateString' => '4:30 PM, Sep 13, 2022', ], 'August 27, 2022 - 21:00' => [ 'expectedDate' => '2022-08-27T21:00:00+00:00', - 'dateString' => 'August 27, 2022 - 21:00', + 'dateString' => 'August 27, 2022 - 21:00', ], '2021-09-19T14:06:03+00:00' => [ 'expectedDate' => '2021-09-19T14:06:03+00:00', - 'dateString' => '2021-09-19T14:06:03+00:00', + 'dateString' => '2021-09-19T14:06:03+00:00', ], 'Eastern Time timezone' => [ 'expectedDate' => '2022-09-30T00:00:00-05:00', - 'dateString' => 'September 30, 2022, 12:00 a.m. ET', + 'dateString' => 'September 30, 2022, 12:00 a.m. ET', ], 'German date time string' => [ 'expectedDate' => '2022-10-05T16:34:00+02:00', - 'dateString' => '05 Okt 2022 16:34:00 +0200', + 'dateString' => '05 Okt 2022 16:34:00 +0200', ], '(Coordinated Universal Time)' => [ 'expectedDate' => '2022-12-30T14:29:10+00:00', - 'dateString' => 'Fri Dec 30 2022 14:29:10 GMT+0000 (Coordinated Universal Time)', + 'dateString' => 'Fri Dec 30 2022 14:29:10 GMT+0000 (Coordinated Universal Time)', ], 'Double HTML encode' => [ 'expectedDate' => '2015-05-22T08:48:00+12:00', - 'dateString' => '2015-05-22T08:48:00+12:00' + 'dateString' => '2015-05-22T08:48:00+12:00' ], '2023-04-02\T17:22:42+05:30' => [ 'expectedDate' => '2023-04-02T17:22:42+05:30', - 'dateString' => '2023-04-02\T17:22:42+05:30' + 'dateString' => '2023-04-02\T17:22:42+05:30' ], '2025-03-07T08:54:14.341+01:00[Europe/Berlin]' => [ 'expectedDate' => '2025-03-07T08:54:14+01:00', - 'dateString' => '2025-03-07T08:54:14.341+01:00[Europe/Berlin]' + 'dateString' => '2025-03-07T08:54:14.341+01:00[Europe/Berlin]' ], ]; } @@ -155,53 +155,54 @@ class DateTimeFormatTest extends MockedTestCase */ public function testConvertRelative() { - $now = DateTimeFormat::utcNow('U'); + $now = DateTimeFormat::utcNow('U'); $date = DateTimeFormat::utc('now - 3 days', 'U'); $this->assertEquals(259200, $now - $date); } - public function dataConvert() { + public function dataConvert() + { return [ 'unix timestamp' => [ 'expected' => '2025-03-12 16:18:27', - 's' => '1741796307', + 's' => '1741796307', ], 'ATOM' => [ 'expected' => '2022-06-02 15:58:35', - 's' => '2022-06-02T16:58:35+01:00', + 's' => '2022-06-02T16:58:35+01:00', ], 'COOKIE' => [ 'expected' => '2022-06-02 14:58:35', - 's' => 'Thursday, 02-Jun-2022 16:58:35 Africa/Cairo', + 's' => 'Thursday, 02-Jun-2022 16:58:35 Africa/Cairo', ], 'ISO 8601/RFC 3339' => [ 'expected' => '2022-06-02 13:58:35', - 's' => '2022-06-02T16:58:35+0300', + 's' => '2022-06-02T16:58:35+0300', ], 'RFC 822/RFC 1036' => [ 'expected' => '2022-06-02 12:58:35', - 's' => 'Thu, 02 Jun 22 16:58:35 +0400', + 's' => 'Thu, 02 Jun 22 16:58:35 +0400', ], 'RFC 850' => [ 'expected' => '2022-06-02 11:58:35', - 's' => 'Thursday, 02-Jun-22 16:58:35 Indian/Kerguelen', + 's' => 'Thursday, 02-Jun-22 16:58:35 Indian/Kerguelen', ], 'RFC 1123/RFC 2822/RSS' => [ 'expected' => '2022-06-02 10:58:35', - 's' => 'Thu, 02 Jun 2022 16:58:35 +0600', + 's' => 'Thu, 02 Jun 2022 16:58:35 +0600', ], 'RFC 3339/W3C' => [ 'expected' => '2025-03-07 01:54:14', - 's' => '2025-03-07T08:54:14+07:00', + 's' => '2025-03-07T08:54:14+07:00', ], 'RFC 3339 extended' => [ 'expected' => '2025-03-07 00:54:14', - 's' => '2025-03-07T08:54:14.341+08:00', + 's' => '2025-03-07T08:54:14.341+08:00', ], 'RFC 7231' => [ 'expected' => '2022-06-02 07:58:35', - 's' => 'Thu, 02 Jun 2022 16:58:35 Asia/Tokyo', + 's' => 'Thu, 02 Jun 2022 16:58:35 Asia/Tokyo', ], ]; } From 5c1b5bae616876c363c44796aaee4004e562b6b5 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 29 Mar 2025 09:07:11 +0000 Subject: [PATCH 5/6] Added more logging to track down issue 14800 --- src/Module/Photo.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Module/Photo.php b/src/Module/Photo.php index 8843e82b0a..861e0b936a 100644 --- a/src/Module/Photo.php +++ b/src/Module/Photo.php @@ -130,6 +130,7 @@ class Photo extends BaseApi $photo = MPhoto::getPhoto($photoid, $scale, self::getCurrentUserID()); if ($photo === false) { + $this->logger->notice('Photo was not loaded', ['parameters' => $this->parameters, 'id' => $photoid]); throw new HTTPException\NotFoundException(DI::l10n()->t('The Photo with id %s is not available.', $photoid)); } } @@ -137,6 +138,7 @@ class Photo extends BaseApi $fetch = microtime(true) - $stamp; if ($photo === false) { + $this->logger->notice('Photo was not loaded', ['parameters' => $this->parameters]); throw new HTTPException\NotFoundException(); } @@ -151,6 +153,7 @@ class Photo extends BaseApi $mimetype = $photo['type']; } if (empty($imgdata) && empty($photo['blurhash'])) { + $this->logger->notice('Image data was not loaded', ['parameters' => $this->parameters, 'class' => $photo['backend-class'], 'ref' => $photo['backend-ref']]); throw new HTTPException\NotFoundException(); } @@ -317,7 +320,11 @@ class Photo extends BaseApi $photo = MPhoto::selectFirst([], ['scale' => $scale, 'uid' => $contact['uid'], 'profile' => 1]); if (!empty($photo)) { return $photo; + } else { + $this->logger->notice('Profile photo was not loaded', ['scale' => $scale, 'uid' => $contact['uid']]); } + } else { + $this->logger->notice('Local Contact was not found', ['url' => $contact['nurl']]); } } @@ -333,6 +340,7 @@ class Photo extends BaseApi if (!empty($photo)) { return $photo; } else { + $this->logger->notice('Photo was not loaded', ['resource-id' => $resourceid]); $url = $contact['avatar']; } } else { From 6cab9c010d6d9c860fc11478f7729c87a791fd5d Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 31 Mar 2025 20:38:37 +0000 Subject: [PATCH 6/6] Fix blurred images --- src/Module/Photo.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Module/Photo.php b/src/Module/Photo.php index 861e0b936a..8faef5aa6d 100644 --- a/src/Module/Photo.php +++ b/src/Module/Photo.php @@ -348,6 +348,8 @@ class Photo extends BaseApi } } elseif (!empty($contact['avatar'])) { $url = $contact['avatar']; + } else { + $url = ''; } // If it is a local link, we save resources by just redirecting to it. @@ -389,8 +391,6 @@ class Photo extends BaseApi } } - $url = ''; - if (empty($mimetext) && !empty($contact['blurhash'])) { $image = new Image('', image_type_to_mime_type(IMAGETYPE_WEBP)); $image->getFromBlurHash($contact['blurhash'], $customsize, $customsize);