From 39e1776fa997b735e5c6aa93311f84d70dcee123 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Sun, 21 Jun 2026 11:05:41 +0200 Subject: [PATCH] chore: Change the source of read/read later/dismissed links --- src/controllers/Bookmarks.php | 14 +- src/controllers/Read.php | 15 +-- src/controllers/api/v1/Links.php | 44 ++++++- src/models/ReadLaterSource.php | 62 +++++++++ src/models/ReadSource.php | 62 +++++++++ src/models/Source.php | 31 +++++ src/models/UrlStatus.php | 32 +++++ src/models/User.php | 58 ++++++++- src/models/dao/Link.php | 135 +++++++++++++++++--- src/models/dao/links/NewsQueries.php | 50 ++------ src/services/DataExporter.php | 18 ++- src/views/bookmarks/index.html.twig | 8 +- src/views/read/index.html.twig | 8 +- src/views/sources/exportation.atom.xml.twig | 40 ++++++ tests/controllers/collections/ReadTest.php | 2 - tests/controllers/links/ReadTest.php | 6 - tests/services/DataExporterTest.php | 27 ---- 17 files changed, 476 insertions(+), 136 deletions(-) create mode 100644 src/models/ReadLaterSource.php create mode 100644 src/models/ReadSource.php create mode 100644 src/models/Source.php create mode 100644 src/views/sources/exportation.atom.xml.twig diff --git a/src/controllers/Bookmarks.php b/src/controllers/Bookmarks.php index 09d239655..d11871a6c 100644 --- a/src/controllers/Bookmarks.php +++ b/src/controllers/Bookmarks.php @@ -99,23 +99,17 @@ public function create(Request $request): Response public function index(Request $request): Response { $user = auth\CurrentUser::require(); + $read_later_source = $user->readLaterSource(); - $bookmarks = $user->bookmarks(); $page = $request->parameters->getInteger('page', 1); - $number_links = models\Link::countByCollectionId($bookmarks->id); + $number_links = $read_later_source->countLinks(); $pagination = new utils\Pagination($number_links, 29, $page); - $links = $bookmarks->links( - ['published_at', 'number_notes'], - [ - 'offset' => $pagination->currentOffset(), - 'limit' => $pagination->numberPerPage(), - ] - ); + $links = $read_later_source->links($pagination); return Response::ok('bookmarks/index.html.twig', [ - 'collection' => $bookmarks, + 'read_later_source' => $read_later_source, 'links' => $links, 'pagination' => $pagination, ]); diff --git a/src/controllers/Read.php b/src/controllers/Read.php index 0cf7f35ce..acdf295eb 100644 --- a/src/controllers/Read.php +++ b/src/controllers/Read.php @@ -30,24 +30,17 @@ class Read extends BaseController public function index(Request $request): Response { $user = auth\CurrentUser::require(); + $read_source = $user->readSource(); - $read_list = $user->readList(); $page = $request->parameters->getInteger('page', 1); - $number_links = models\Link::countByCollectionId($read_list->id); - + $number_links = $read_source->countLinks(); $pagination = new utils\Pagination($number_links, 30, $page); - $links = $read_list->links( - ['published_at', 'number_notes'], - [ - 'offset' => $pagination->currentOffset(), - 'limit' => $pagination->numberPerPage(), - ] - ); + $links = $read_source->links($pagination); return Response::ok('read/index.html.twig', [ - 'collection' => $read_list, + 'read_source' => $read_source, 'links' => $links, 'pagination' => $pagination, ]); diff --git a/src/controllers/api/v1/Links.php b/src/controllers/api/v1/Links.php index 3026fb7ed..db1001b76 100644 --- a/src/controllers/api/v1/Links.php +++ b/src/controllers/api/v1/Links.php @@ -32,19 +32,34 @@ public function index(Request $request): Response { $user = auth\CurrentUser::require(); - $collection_id = $request->parameters->getString('collection'); + $collection_id = $request->parameters->getString('collection', ''); $pagination_page = $request->parameters->getInteger('page', 1); $pagination_per_page = $request->parameters->getInteger('per_page', 30); $pagination_per_page = min(100, max(1, $pagination_per_page)); - $collection = null; if ($collection_id === 'to-read') { - $collection = $user->bookmarks(); + return $this->indexSource($user->readLaterSource(), $pagination_page, $pagination_per_page); } elseif ($collection_id === 'read') { - $collection = $user->readList(); - } elseif ($collection_id) { - $collection = models\Collection::find($collection_id); + return $this->indexSource($user->readSource(), $pagination_page, $pagination_per_page); + } else { + return $this->indexCollection($collection_id, $pagination_page, $pagination_per_page); } + } + + /** + * @response 401 + * If the request is not correctly authenticated. + * @response 403 + * If the user cannot access the collection. + * @response 404 + * If the collection does not exist. + * @response 200 + */ + private function indexCollection(string $collection_id, int $pagination_page, int $pagination_per_page): Response + { + $user = auth\CurrentUser::require(); + + $collection = models\Collection::find($collection_id); if (!$collection) { return Response::json(404, [ @@ -79,6 +94,23 @@ public function index(Request $request): Response }, $links)); } + /** + * @response 200 + */ + private function indexSource(models\Source $source, int $pagination_page, int $pagination_per_page): Response + { + $user = auth\CurrentUser::require(); + + $number_links = $source->countLinks(); + $pagination = new utils\Pagination($number_links, $pagination_per_page, $pagination_page); + + $links = $source->links($pagination); + + return Response::json(200, array_map(function (models\Link $link) use ($user): array { + return $link->toJson(context_user: $user); + }, $links)); + } + /** * @request_param string id * diff --git a/src/models/ReadLaterSource.php b/src/models/ReadLaterSource.php new file mode 100644 index 000000000..bb22d32b0 --- /dev/null +++ b/src/models/ReadLaterSource.php @@ -0,0 +1,62 @@ + + * @license http://www.gnu.org/licenses/agpl-3.0.en.html AGPL + */ +class ReadLaterSource extends Source +{ + public function __construct( + public readonly User $owner, + ) { + } + + public function name(): string + { + return _('To read'); + } + + public function description(): string + { + return _('Place here the links you want to consult later on.'); + } + + public function url(): string + { + return \Minz\Url::absoluteFor('bookmarks'); + } + + public function owner(): User + { + return $this->owner; + } + + /** + * @return Link[] + */ + public function links(?utils\Pagination $pagination = null): array + { + return Link::listReadLater($this->owner, $pagination); + } + + public function countLinks(): int + { + return Link::countReadLater($this->owner); + } + + /** + * Return a tag URI that can be used as Atom id + * + * @see https://www.rfc-editor.org/rfc/rfc4151.txt + */ + public function tagUri(): string + { + $host = \App\Configuration::$url_options['host']; + $date = $this->owner->created_at->format('Y-m-d'); + return "tag:{$host},{$date}:{$this->owner->id}/read/later"; + } +} diff --git a/src/models/ReadSource.php b/src/models/ReadSource.php new file mode 100644 index 000000000..519316dc1 --- /dev/null +++ b/src/models/ReadSource.php @@ -0,0 +1,62 @@ + + * @license http://www.gnu.org/licenses/agpl-3.0.en.html AGPL + */ +class ReadSource extends Source +{ + public function __construct( + private readonly User $owner, + ) { + } + + public function name(): string + { + return _('Links read'); + } + + public function description(): string + { + return _('Find here all the links you’ve marked as read.'); + } + + public function url(): string + { + return \Minz\Url::absoluteFor('read list'); + } + + public function owner(): User + { + return $this->owner; + } + + /** + * @return Link[] + */ + public function links(?utils\Pagination $pagination = null): array + { + return Link::listRead($this->owner, $pagination); + } + + public function countLinks(): int + { + return Link::countRead($this->owner); + } + + /** + * Return a tag URI that can be used as Atom id + * + * @see https://www.rfc-editor.org/rfc/rfc4151.txt + */ + public function tagUri(): string + { + $host = \App\Configuration::$url_options['host']; + $date = $this->owner->created_at->format('Y-m-d'); + return "tag:{$host},{$date}:{$this->owner->id}/read"; + } +} diff --git a/src/models/Source.php b/src/models/Source.php new file mode 100644 index 000000000..a0e7fb5d6 --- /dev/null +++ b/src/models/Source.php @@ -0,0 +1,31 @@ + + * @license http://www.gnu.org/licenses/agpl-3.0.en.html AGPL + */ +abstract class Source +{ + abstract public function name(): string; + + abstract public function description(): string; + + abstract public function url(): string; + + abstract public function owner(): User; + + /** + * @return Link[] + */ + abstract public function links(?utils\Pagination $pagination = null): array; + + abstract public function countLinks(): int; + + abstract public function tagUri(): string; +} diff --git a/src/models/UrlStatus.php b/src/models/UrlStatus.php index 84f018bea..f546b7d0a 100644 --- a/src/models/UrlStatus.php +++ b/src/models/UrlStatus.php @@ -43,6 +43,21 @@ public function __construct(User $user, string $url) $this->url_hash = utils\Belt::hashUrl($url); } + public function isRead(): bool + { + return $this->read_at !== null; + } + + public function isReadLater(): bool + { + return $this->read_later_at !== null; + } + + public function isDismissed(): bool + { + return $this->dismissed_at !== null; + } + /** * Mark the links as read for the user. * @@ -248,6 +263,23 @@ public static function unmark(User $user, Link|array $links): void $statement->execute($values); } + /** + * Return the existing UrlStatus for this user and url if any, or build one otherwise. + */ + public static function findOrBuild(User $user, string $url): self + { + $url_status = self::findBy([ + 'user_id' => $user->id, + 'url_hash' => utils\Belt::hashUrl($url), + ]); + + if (!$url_status) { + $url_status = new self($user, $url); + } + + return $url_status; + } + /** * @see dao\BulkQueries::bulkInsertOnConflict * diff --git a/src/models/User.php b/src/models/User.php index 0e3e9f7c5..ca450816c 100644 --- a/src/models/User.php +++ b/src/models/User.php @@ -626,13 +626,29 @@ public function suggestedLinksFor(Link $link): array return $suggested_links; } + /** + * Return the source of read links for the current user. + */ + public function readSource(): ReadSource + { + return new ReadSource($this); + } + + /** + * Return the source of links to read later for the current user. + */ + public function readLaterSource(): ReadLaterSource + { + return new ReadLaterSource($this); + } + /** * Return whether the user has read the link or not. */ public function hasRead(Link $link): bool { - $read_list = $this->readList(); - return Link::isUrlInCollectionId($read_list->id, $link->url); + $url_status = $this->urlStatusOfLink($link); + return $url_status->isRead(); } /** @@ -640,8 +656,8 @@ public function hasRead(Link $link): bool */ public function hasReadLater(Link $link): bool { - $bookmarks = $this->bookmarks(); - return Link::isUrlInCollectionId($bookmarks->id, $link->url); + $url_status = $this->urlStatusOfLink($link); + return $url_status->isReadLater(); } /** @@ -649,8 +665,8 @@ public function hasReadLater(Link $link): bool */ public function hasDismissed(Link $link): bool { - $never_list = $this->neverList(); - return Link::isUrlInCollectionId($never_list->id, $link->url); + $url_status = $this->urlStatusOfLink($link); + return $url_status->isDismissed(); } /** @@ -668,6 +684,7 @@ public function markAsRead(Link|array $links): void LinkToCollection::markAsRead($this, $link_ids); UrlStatus::markAsRead($this, $links); + $this->unmemoizeUrlStatusesOfLinks($links); $news = $this->news(); $news->removeLinks($links, sync_publication_frequency: false); @@ -688,6 +705,7 @@ public function unmarkAsRead(Link|array $links): void LinkToCollection::markAsUnread($this, $link_ids); UrlStatus::unmarkAsRead($this, $links); + $this->unmemoizeUrlStatusesOfLinks($links); } /** @@ -705,6 +723,7 @@ public function markAsReadLater(Link|array $links): void LinkToCollection::markToReadLater($this, $link_ids); UrlStatus::markAsReadLater($this, $links); + $this->unmemoizeUrlStatusesOfLinks($links); $news = $this->news(); $news->removeLinks($links, sync_publication_frequency: false); @@ -725,6 +744,7 @@ public function markAsDismissed(Link|array $links): void LinkToCollection::markToNeverRead($this, $link_ids); UrlStatus::markAsDismissed($this, $links); + $this->unmemoizeUrlStatusesOfLinks($links); $news = $this->news(); $news->removeLinks($links, sync_publication_frequency: false); @@ -742,6 +762,32 @@ public function unmark(Link|array $links): void } UrlStatus::unmark($this, $links); + $this->unmemoizeUrlStatusesOfLinks($links); + } + + /** + * Get the UrlStatus corresponding to this user and link. + * + * A UrlStatus is always returned. In case it is unknown to the user, a + * UserStatus is built (but not saved in database). + */ + private function urlStatusOfLink(Link $link): UrlStatus + { + return $this->memoize("url_status_{$link->url}", function () use ($link): UrlStatus { + return UrlStatus::findOrBuild($this, $link->url); + }); + } + + /** + * Unmemoize statuses for the links' urls. + * + * @param Link[] $links + */ + private function unmemoizeUrlStatusesOfLinks(array $links): void + { + foreach ($links as $link) { + $this->unmemoize("url_status_{$link->url}"); + } } /** diff --git a/src/models/dao/Link.php b/src/models/dao/Link.php index 9cebc8d2b..cf08d4efe 100644 --- a/src/models/dao/Link.php +++ b/src/models/dao/Link.php @@ -514,25 +514,61 @@ public static function countByCollectionId(string $collection_id, array $options return intval($statement->fetchColumn()); } - public function numberCollectionsForUser(\App\models\User $user): int + /** + * Return the list of read later links of the given user. + * + * @return models\Link[] + */ + public static function listReadLater(models\User $user, ?utils\Pagination $pagination): array { + $parameters = [ + ':user_id' => $user->id, + ]; + + $pagination_clause = ''; + if ($pagination) { + $pagination_clause = 'LIMIT :limit OFFSET :offset'; + $parameters[':limit'] = $pagination->numberPerPage(); + $parameters[':offset'] = $pagination->currentOffset(); + } + $sql = <<prepare($sql); + $statement->execute($parameters); + + return self::fromDatabaseRows($statement->fetchAll()); + } + + /** + * Return the count of read later links of the given user. + */ + public static function countReadLater(models\User $user): int + { + $sql = <<prepare($sql); $statement->execute([ - ':link_url_hash' => $this->url_hash, ':user_id' => $user->id, ]); @@ -540,28 +576,89 @@ public function numberCollectionsForUser(\App\models\User $user): int } /** - * Return whether or not the given link URL is in the collection. + * Return the list of read links of the given user. + * + * @return models\Link[] */ - public static function isUrlInCollectionId(string $collection_id, string $url): bool + public static function listRead(models\User $user, ?utils\Pagination $pagination): array { - $sql = <<<'SQL' - SELECT 1 - FROM links l, links_to_collections lc + $parameters = [ + ':user_id' => $user->id, + ]; - WHERE l.url_hash = :url_hash + $pagination_clause = ''; + if ($pagination) { + $pagination_clause = 'LIMIT :limit OFFSET :offset'; + $parameters[':limit'] = $pagination->numberPerPage(); + $parameters[':offset'] = $pagination->currentOffset(); + } + + $sql = <<prepare($sql); + $statement->execute($parameters); + + return self::fromDatabaseRows($statement->fetchAll()); + } + + /** + * Return the count of read links of the given user. + */ + public static function countRead(models\User $user): int + { + $sql = <<prepare($sql); + $statement->execute([ + ':user_id' => $user->id, + ]); + + return intval($statement->fetchColumn()); + } + + public function numberCollectionsForUser(\App\models\User $user): int + { + $sql = <<prepare($sql); $statement->execute([ - ':collection_id' => $collection_id, - ':url_hash' => utils\Belt::hashUrl($url), + ':link_url_hash' => $this->url_hash, + ':user_id' => $user->id, ]); - return (bool) $statement->fetchColumn(); + return intval($statement->fetchColumn()); } /** diff --git a/src/models/dao/links/NewsQueries.php b/src/models/dao/links/NewsQueries.php index 6d9d71125..d70e33f74 100644 --- a/src/models/dao/links/NewsQueries.php +++ b/src/models/dao/links/NewsQueries.php @@ -36,12 +36,18 @@ public static function listFromFollowedCollections(string $user_id, int $max): a c.id AS source_id FROM collections c, links_to_collections lc, followed_collections fc, links l + LEFT JOIN url_statuses us ON us.user_id = :user_id AND us.url_hash = l.url_hash + WHERE fc.user_id = :user_id AND fc.collection_id = lc.collection_id AND lc.link_id = l.id AND lc.collection_id = c.id + AND us.read_at IS NULL + AND us.read_later_at IS NULL + AND us.dismissed_at IS NULL + AND ( (l.is_hidden = false AND c.is_public = true) OR c.user_id = :user_id @@ -52,25 +58,6 @@ public static function listFromFollowedCollections(string $user_id, int $max): a ) ) - AND NOT EXISTS ( - SELECT 1 - FROM links l_exclude, collections c_exclude, links_to_collections lc_exclude - - WHERE c_exclude.user_id = :user_id - AND l_exclude.user_id = :user_id - AND l_exclude.url_hash = l.url_hash - - AND ( - c_exclude.type = 'news' - OR c_exclude.type = 'bookmarks' - OR c_exclude.type = 'read' - OR c_exclude.type = 'never' - ) - - AND lc_exclude.link_id = l_exclude.id - AND lc_exclude.collection_id = c_exclude.id - ) - AND l.user_id IS DISTINCT FROM :user_id AND lc.created_at >= :until_hard_limit @@ -114,12 +101,18 @@ public static function anyFromFollowedCollections(string $user_id): bool SELECT l.id FROM collections c, links_to_collections lc, followed_collections fc, links l + LEFT JOIN url_statuses us ON us.user_id = :user_id AND us.url_hash = l.url_hash + WHERE fc.user_id = :user_id AND fc.collection_id = lc.collection_id AND lc.link_id = l.id AND lc.collection_id = c.id + AND us.read_at IS NULL + AND us.read_later_at IS NULL + AND us.dismissed_at IS NULL + AND ( (l.is_hidden = false AND c.is_public = true) OR c.user_id = :user_id @@ -130,25 +123,6 @@ public static function anyFromFollowedCollections(string $user_id): bool ) ) - AND NOT EXISTS ( - SELECT 1 - FROM links l_exclude, collections c_exclude, links_to_collections lc_exclude - - WHERE c_exclude.user_id = :user_id - AND l_exclude.user_id = :user_id - AND l_exclude.url_hash = l.url_hash - - AND ( - c_exclude.type = 'news' - OR c_exclude.type = 'bookmarks' - OR c_exclude.type = 'read' - OR c_exclude.type = 'never' - ) - - AND lc_exclude.link_id = l_exclude.id - AND lc_exclude.collection_id = c_exclude.id - ) - AND l.user_id IS DISTINCT FROM :user_id AND lc.created_at >= :until_hard_limit diff --git a/src/services/DataExporter.php b/src/services/DataExporter.php index acaf2f72d..f8b0f1ffb 100644 --- a/src/services/DataExporter.php +++ b/src/services/DataExporter.php @@ -43,10 +43,9 @@ public function export(string $user_id): string $files = []; $files['metadata.json'] = $this->generateMetadata(); $files['followed.opml.xml'] = $this->generateOpml($user); - $files['bookmarks.atom.xml'] = $this->generateCollection($user->bookmarks()); $files['news.atom.xml'] = $this->generateCollection($user->news()); - $files['read.atom.xml'] = $this->generateCollection($user->readList()); - $files['never.atom.xml'] = $this->generateCollection($user->neverList()); + $files['bookmarks.atom.xml'] = $this->generateSource($user->readLaterSource()); + $files['read.atom.xml'] = $this->generateSource($user->readSource()); $collections = $user->collections(); foreach ($collections as $collection) { @@ -124,6 +123,19 @@ private function generateCollection(models\Collection $collection): string return self::formatXML($view->render()); } + /** + * Return an Atom representation of the given source. + */ + private function generateSource(models\Source $source): string + { + $view = new \Minz\Template\Twig('sources/exportation.atom.xml.twig', [ + 'source' => $source, + 'links' => $source->links(), + ]); + + return self::formatXML($view->render()); + } + /** * Return an Atom representation of the given link notes. */ diff --git a/src/views/bookmarks/index.html.twig b/src/views/bookmarks/index.html.twig index 300584dfc..68a43b085 100644 --- a/src/views/bookmarks/index.html.twig +++ b/src/views/bookmarks/index.html.twig @@ -6,7 +6,7 @@ {% set current_url_params = { page: pagination.currentPage } %} {% endif %} -{% block title %}{{ collection.name() }}{% endblock %} +{% block title %}{{ read_later_source.name }}{% endblock %} {% block canonical %}{{ url_full('bookmarks', current_url_params) }}{% endblock %} {% block layout_header %} @@ -18,16 +18,16 @@ {% endblock %} {% block back %} - {{ include('layouts/_back.html.twig', { title: collection.name(), reset: true }) }} + {{ include('layouts/_back.html.twig', { title: read_later_source.name, reset: true }) }} {% endblock %} {% block body %} -

{{ collection.name() }}

+

{{ read_later_source.name }}

- {{ t('Place here the links you want to consult later on.') }} + {{ read_later_source.description }}

{{ include('links/_pagination_count.html.twig') }} diff --git a/src/views/read/index.html.twig b/src/views/read/index.html.twig index 329aead85..ff28594a5 100644 --- a/src/views/read/index.html.twig +++ b/src/views/read/index.html.twig @@ -6,7 +6,7 @@ {% set current_url_params = { page: pagination.currentPage } %} {% endif %} -{% block title %}{{ collection.name() }}{% endblock %} +{% block title %}{{ read_source.name }}{% endblock %} {% block canonical %}{{ url_full('read list', current_url_params) }}{% endblock %} {% block layout_header %} @@ -18,16 +18,16 @@ {% endblock %} {% block back %} - {{ include('layouts/_back.html.twig', { title: collection.name(), reset: true }) }} + {{ include('layouts/_back.html.twig', { title: read_source.name, reset: true }) }} {% endblock %} {% block body %} -

{{ collection.name() }}

+

{{ read_source.name }}

- {{ t('Find here all the links you’ve marked as read.') }} + {{ read_source.description }}

{{ include('links/_pagination_count.html.twig') }} diff --git a/src/views/sources/exportation.atom.xml.twig b/src/views/sources/exportation.atom.xml.twig new file mode 100644 index 000000000..b68cafcf3 --- /dev/null +++ b/src/views/sources/exportation.atom.xml.twig @@ -0,0 +1,40 @@ + + + {{ source.name }} + {% if source.description %} + + {% endif %} + + + + {{ source.tagUri }} + + {{ source.owner.username }} + + {{ app.user_agent }} + + {% if links %} + {{ links[0].published_at.format(constant('DATE_ATOM')) }} + {% else %} + {{ date().format(constant('DATE_ATOM')) }} + {% endif %} + + {% for link in links %} + + {{ link.title }} + {{ link.tagUri }} + + + + + {% if link.is_hidden %} + + {% endif %} + + {{ link.published_at.format(constant('DATE_ATOM')) }} + {{ link.published_at.format(constant('DATE_ATOM')) }} + + + + {% endfor %} + diff --git a/tests/controllers/collections/ReadTest.php b/tests/controllers/collections/ReadTest.php index bc58b18bc..9e877da8d 100644 --- a/tests/controllers/collections/ReadTest.php +++ b/tests/controllers/collections/ReadTest.php @@ -415,7 +415,6 @@ public function testNeverMarksNewsLinksToBeDismissedAndRedirects(): void $link = LinkFactory::create([ 'user_id' => $user->id, ]); - $user->markAsReadLater($link); $news->addLinks([$link]); $response = $this->appRun('POST', "/collections/{$news->id}/read/never", [ @@ -424,7 +423,6 @@ public function testNeverMarksNewsLinksToBeDismissedAndRedirects(): void $this->assertResponseCode($response, 302, '/'); $this->assertTrue($user->hasDismissed($link), 'The link should be has been dismissed.'); - $this->assertFalse($user->hasReadLater($link), 'The link should not be to read later.'); $this->assertFalse($news->hasLink($link), 'The link should not be in news.'); } diff --git a/tests/controllers/links/ReadTest.php b/tests/controllers/links/ReadTest.php index d3826da11..3ebd2d954 100644 --- a/tests/controllers/links/ReadTest.php +++ b/tests/controllers/links/ReadTest.php @@ -266,7 +266,6 @@ public function testNeverMarksToDismiss(): void $link = LinkFactory::create([ 'user_id' => $user->id, ]); - $user->markAsReadLater($link); $news->addLinks([$link]); $response = $this->appRun('POST', "/links/{$link->id}/read/never", [ @@ -275,7 +274,6 @@ public function testNeverMarksToDismiss(): void $this->assertResponseCode($response, 302, '/'); $this->assertTrue($user->hasDismissed($link)); - $this->assertFalse($user->hasReadLater($link)); $this->assertFalse($news->hasLink($link)); } @@ -314,7 +312,6 @@ public function testNeverRedirectsToLoginIfNotConnected(): void $link = LinkFactory::create([ 'user_id' => $user->id, ]); - $user->markAsReadLater($link); $news->addLinks([$link]); $response = $this->appRun('POST', "/links/{$link->id}/read/never", [ @@ -323,7 +320,6 @@ public function testNeverRedirectsToLoginIfNotConnected(): void $this->assertResponseCode($response, 302, '/login?redirect_to=%2F'); $this->assertFalse($user->hasDismissed($link)); - $this->assertTrue($user->hasReadLater($link)); $this->assertTrue($news->hasLink($link)); } @@ -334,7 +330,6 @@ public function testNeverFailsIfCsrfIsInvalid(): void $link = LinkFactory::create([ 'user_id' => $user->id, ]); - $user->markAsReadLater($link); $news->addLinks([$link]); $response = $this->appRun('POST', "/links/{$link->id}/read/never", [ @@ -345,7 +340,6 @@ public function testNeverFailsIfCsrfIsInvalid(): void $error = utils\Notification::popError(); $this->assertStringContainsString('A security verification failed', $error); $this->assertFalse($user->hasDismissed($link)); - $this->assertTrue($user->hasReadLater($link)); $this->assertTrue($news->hasLink($link)); } diff --git a/tests/services/DataExporterTest.php b/tests/services/DataExporterTest.php index 8e293f537..f139aaf79 100644 --- a/tests/services/DataExporterTest.php +++ b/tests/services/DataExporterTest.php @@ -185,8 +185,6 @@ public function testExportCreatesBookmarksFile(): void $feed_content = $this->zipGetContents($filepath, 'bookmarks.atom.xml'); $feed = \SpiderBits\feeds\Feed::fromText($feed_content); - $this->assertSame(1, count($feed->categories)); - $this->assertSame('Flus:type:bookmarks', $feed->categories['Flus:type:bookmarks']); $this->assertSame(1, count($feed->entries)); $entry = $feed->entries[0]; $this->assertSame($link_url, $entry->link); @@ -235,31 +233,6 @@ public function testExportCreatesReadFile(): void $feed_content = $this->zipGetContents($filepath, 'read.atom.xml'); $feed = \SpiderBits\feeds\Feed::fromText($feed_content); - $this->assertSame(1, count($feed->categories)); - $this->assertSame('Flus:type:read', $feed->categories['Flus:type:read']); - $this->assertSame(1, count($feed->entries)); - $entry = $feed->entries[0]; - $this->assertSame($link_url, $entry->link); - } - - public function testExportCreatesNeverFile(): void - { - $data_exporter = new DataExporter($this->exportations_path); - $user = UserFactory::create(); - /** @var string */ - $link_url = $this->fake('url'); - $link = LinkFactory::create([ - 'user_id' => $user->id, - 'url' => $link_url, - ]); - $user->markAsDismissed($link); - - $filepath = $data_exporter->export($user->id); - - $feed_content = $this->zipGetContents($filepath, 'never.atom.xml'); - $feed = \SpiderBits\feeds\Feed::fromText($feed_content); - $this->assertSame(1, count($feed->categories)); - $this->assertSame('Flus:type:never', $feed->categories['Flus:type:never']); $this->assertSame(1, count($feed->entries)); $entry = $feed->entries[0]; $this->assertSame($link_url, $entry->link);