Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions src/controllers/Bookmarks.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
]);
Expand Down
15 changes: 4 additions & 11 deletions src/controllers/Read.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
]);
Expand Down
44 changes: 38 additions & 6 deletions src/controllers/api/v1/Links.php
Original file line number Diff line number Diff line change
Expand Up @@ -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, [
Expand Down Expand Up @@ -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
*
Expand Down
62 changes: 62 additions & 0 deletions src/models/ReadLaterSource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace App\models;

use App\utils;

/**
* @author Marien Fressinaud <dev@marienfressinaud.fr>
* @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";
}
}
62 changes: 62 additions & 0 deletions src/models/ReadSource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace App\models;

use App\utils;

/**
* @author Marien Fressinaud <dev@marienfressinaud.fr>
* @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";
}
}
31 changes: 31 additions & 0 deletions src/models/Source.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace App\models;

use App\utils;

/**
* A source provides a list of links.
*
* @author Marien Fressinaud <dev@marienfressinaud.fr>
* @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;
}
32 changes: 32 additions & 0 deletions src/models/UrlStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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
*
Expand Down
Loading
Loading