Skip to content

Commit 3a5adec

Browse files
chore: Refactor link source into origin system
1 parent 3c0276c commit 3a5adec

31 files changed

Lines changed: 413 additions & 270 deletions

src/assets/stylesheets/components/groups.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
padding-left: var(--space-smaller);
3737
}
3838

39-
.source-group__title {
39+
.origin-group__title {
4040
font-size: var(--font-size-normal);
4141
font-weight: 600;
4242
}

src/assets/stylesheets/components/links.css

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,12 @@
141141
overflow-wrap: anywhere;
142142
}
143143

144-
.link__source {
144+
.link__origin {
145145
font-style: italic;
146146
}
147147

148-
.link__source a {
148+
.link__origin a {
149149
color: currentcolor;
150-
text-decoration: none;
151150
}
152151

153152
.link__notepad {

src/controllers/links/Collections.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ public function update(Request $request): Response
106106

107107
if (!auth\LinksAccess::canUpdate($user, $link)) {
108108
$link = $user->obtainLink($link);
109-
$link->setSourceFrom($from);
109+
$origin = \SpiderBits\Url::absolutize($from, \Minz\Url::baseUrl());
110+
$link->setOrigin($origin);
110111
}
111112

112113
$form = new forms\links\EditLinkCollections(model: $link, options: [

src/controllers/links/Read.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ public function create(Request $request): Response
5555
$link = $user->obtainLink($link);
5656

5757
if (!$link->isPersisted()) {
58-
$link->setSourceFrom($from);
58+
$origin = \SpiderBits\Url::absolutize($from, \Minz\Url::baseUrl());
59+
$link->setOrigin($origin);
5960
$link->save();
6061
}
6162

@@ -103,7 +104,8 @@ public function later(Request $request): Response
103104
$link = $user->obtainLink($link);
104105

105106
if (!$link->isPersisted()) {
106-
$link->setSourceFrom($from);
107+
$origin = \SpiderBits\Url::absolutize($from, \Minz\Url::baseUrl());
108+
$link->setOrigin($origin);
107109
$link->save();
108110
}
109111

src/forms/api/EmptyJournal.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,29 @@ public function links(): array
3535
if ($this->date) {
3636
$options['published_date'] = $this->date;
3737
}
38-
if ($this->source) {
39-
$options['source'] = $this->source;
38+
39+
// @deprecated Can be removed in version 3.0.0.
40+
$source_origin = $this->sourceToOrigin();
41+
if ($source_origin) {
42+
$options['origin'] = $source_origin;
4043
}
4144

4245
$news = $this->user->news();
4346
return $news->links(options: $options);
4447
}
48+
49+
public function sourceToOrigin(): ?string
50+
{
51+
if (!$this->source) {
52+
return null;
53+
}
54+
55+
list($source_type, $source_id) = explode('#', $this->source, 2);
56+
57+
return match ($source_type) {
58+
'user' => \Minz\Url::absoluteFor('profile', ['id' => $source_id]),
59+
'collection' => \Minz\Url::absoluteFor('collection', ['id' => $source_id]),
60+
default => null,
61+
};
62+
}
4563
}

src/forms/traits/CollectionLinks.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ trait CollectionLinks
1818
public ?\DateTimeImmutable $date = null;
1919

2020
#[Form\Field]
21-
public string $source = '';
21+
public string $origin = '';
2222

2323
private string $from = '';
2424

@@ -34,8 +34,8 @@ public function links(): array
3434
if ($this->date) {
3535
$options['published_date'] = $this->date;
3636
}
37-
if ($this->source) {
38-
$options['source'] = $this->source;
37+
if ($this->origin) {
38+
$options['origin'] = $this->origin;
3939
}
4040

4141
$options['hidden'] = auth\Access::can($user, 'viewHiddenLinks', $collection);
@@ -48,7 +48,7 @@ public function links(): array
4848
foreach ($links as $link) {
4949
if (!$link->isPersisted()) {
5050
$link->created_at = \Minz\Time::now();
51-
$link->setSourceFrom($this->from);
51+
$link->setOrigin($this->from);
5252
$links_to_create[] = $link;
5353
}
5454
}
@@ -61,6 +61,8 @@ public function links(): array
6161
#[Form\OnHandleRequest]
6262
public function setFrom(Request $request): void
6363
{
64-
$this->from = utils\RequestHelper::from($request);
64+
$from = utils\RequestHelper::from($request);
65+
$from = \SpiderBits\Url::absolutize($from, \Minz\Url::baseUrl());
66+
$this->from = $from;
6567
}
6668
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
namespace App\migrations;
4+
5+
class Migration202605140003AddOriginToLinks
6+
{
7+
public function migrate(): bool
8+
{
9+
$database = \Minz\Database::get();
10+
11+
$database->exec(<<<'SQL'
12+
ALTER TABLE links
13+
ADD COLUMN origin TEXT NOT NULL DEFAULT '';
14+
15+
CREATE INDEX idx_links_origin ON links(origin) WHERE origin != '';
16+
SQL);
17+
18+
$statement = $database->prepare(<<<'SQL'
19+
UPDATE links
20+
SET origin = :base_url || '/p/' || source_resource_id
21+
WHERE source_type = 'user';
22+
SQL);
23+
24+
$statement->execute([
25+
':base_url' => \Minz\Url::baseUrl(),
26+
]);
27+
28+
$statement = $database->prepare(<<<'SQL'
29+
UPDATE links
30+
SET origin = :base_url || '/collections/' || source_resource_id
31+
WHERE source_type = 'collection';
32+
SQL);
33+
34+
$statement->execute([
35+
':base_url' => \Minz\Url::baseUrl(),
36+
]);
37+
38+
return true;
39+
}
40+
41+
public function rollback(): bool
42+
{
43+
$database = \Minz\Database::get();
44+
45+
$database->exec(<<<'SQL'
46+
DROP INDEX idx_links_origin;
47+
48+
ALTER TABLE links
49+
DROP COLUMN origin;
50+
SQL);
51+
52+
return true;
53+
}
54+
}

src/models/Collection.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ public function publishers(): array
276276
* @param string[] $selected_computed_props
277277
* @param array{
278278
* 'published_date'?: ?\DateTimeImmutable,
279-
* 'source'?: ?string,
279+
* 'origin'?: ?string,
280280
* 'hidden'?: bool,
281281
* 'offset'?: int,
282282
* 'limit'?: int|'ALL',

src/models/Journal.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@ public function fill(int $max): int
3030
foreach ($links as $news_link) {
3131
$link = $this->user->obtainLink($news_link);
3232

33-
// If the link has already a source info, we want to keep it (it
34-
// might have been get via a followed collection, and put in the
35-
// bookmarks then)
36-
if (!$link->source_type && $news_link->source_news_type !== null) {
37-
$link->source_type = $news_link->source_news_type;
38-
$link->source_resource_id = $news_link->source_news_resource_id;
33+
// If the link has already an origin info, we want to keep it.
34+
// Otherwise, we use the initial collection URL.
35+
if (!$link->origin) {
36+
$collection_url = \Minz\Url::absoluteFor('collection', [
37+
'id' => $news_link->initial_collection_id,
38+
]);
39+
$link->setOrigin($collection_url);
3940
}
4041

4142
// Make sure to reset this value: it will be set to true later with

src/models/Link.php

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ class Link
6161
#[Database\Column]
6262
public ?string $image_filename = null;
6363

64+
#[Database\Column]
65+
public string $origin = '';
66+
6467
#[Database\Column]
6568
public string $user_id;
6669

@@ -85,10 +88,7 @@ class Link
8588
public array $tags = [];
8689

8790
#[Database\Column(computed: true)]
88-
public ?string $source_news_type = null;
89-
90-
#[Database\Column(computed: true)]
91-
public ?string $source_news_resource_id = null;
91+
public ?string $initial_collection_id = null;
9292

9393
#[Database\Column(computed: true)]
9494
public ?\DateTimeImmutable $published_at = null;
@@ -160,7 +160,7 @@ public static function copy(self $link, string $user_id): self
160160
$link_copied->fetched_code = $link->fetched_code;
161161
$link_copied->fetched_count = $link->fetched_count;
162162
$link_copied->fetched_retry_at = $link->fetched_retry_at;
163-
$link_copied->source_type = '';
163+
$link_copied->setOrigin('');
164164

165165
return $link_copied;
166166
}
@@ -321,51 +321,63 @@ public function numberNotes(): int
321321
}
322322
}
323323

324-
public function sourceCollection(): ?Collection
324+
/**
325+
* Set the origin of the link.
326+
*
327+
* It is useful to keep the old source_type and source_resource_id columns
328+
* in sync even if they are not used anymore. This is to ease an eventual
329+
* rollback if the new system doesn't work or isn't efficient enough.
330+
*/
331+
public function setOrigin(string $origin): void
325332
{
326-
if (
327-
$this->source_type !== 'collection' ||
328-
!$this->source_resource_id
329-
) {
330-
return null;
331-
}
333+
$this->origin = $origin;
332334

333-
return Collection::find($this->source_resource_id);
334-
}
335+
$this->source_type = '';
336+
$this->source_resource_id = null;
335337

336-
public function sourceUser(): ?User
337-
{
338-
if (
339-
$this->source_type !== 'user' ||
340-
!$this->source_resource_id
341-
) {
342-
return null;
343-
}
338+
if ($origin) {
339+
list($source_type, $source_resource_id) = utils\SourceHelper::extractFromPath($origin);
344340

345-
return User::find($this->source_resource_id);
341+
if ($source_type) {
342+
$this->source_type = $source_type;
343+
$this->source_resource_id = $source_resource_id;
344+
}
345+
}
346346
}
347347

348-
public function source(): User|Collection|null
348+
public function origin(): ?Origin
349349
{
350-
if ($this->source_type == 'user') {
351-
return $this->sourceUser();
352-
} elseif ($this->source_type == 'collection') {
353-
return $this->sourceCollection();
354-
} else {
350+
if (!$this->origin) {
355351
return null;
356352
}
353+
354+
return new Origin($this->origin);
357355
}
358356

359357
/**
360-
* Set the source properties of the link if "from" is a supported internal path.
358+
* Return the (deprecated) source.
359+
*
360+
* @deprecated
361361
*/
362-
public function setSourceFrom(string $from): void
362+
public function source(): ?string
363363
{
364-
list($source_type, $source_resource_id) = utils\SourceHelper::extractFromPath($from);
365-
if ($source_type) {
366-
$this->source_type = $source_type;
367-
$this->source_resource_id = $source_resource_id;
364+
$origin = $this->origin();
365+
366+
if (!$origin || !$origin->model) {
367+
return null;
368368
}
369+
370+
$source_type = match ($origin->model::class) {
371+
User::class => 'user',
372+
Collection::class => 'collection',
373+
default => '',
374+
};
375+
376+
if (!$source_type) {
377+
return null;
378+
}
379+
380+
return "{$source_type}#{$origin->model->id}";
369381
}
370382

371383
/**
@@ -530,9 +542,11 @@ public static function hashUrl(string $url): string
530542
*/
531543
public function toJson(User $context_user): array
532544
{
545+
$origin_model = $this->origin();
533546
$source = null;
534-
if ($this->source_type) {
535-
$source = "{$this->source_type}#{$this->source_resource_id}";
547+
548+
if ($context_user->id === $this->user_id && $origin_model) {
549+
$source = $this->source();
536550
}
537551

538552
return [
@@ -543,7 +557,7 @@ public function toJson(User $context_user): array
543557
'is_hidden' => $this->is_hidden,
544558
'reading_time' => $this->reading_time,
545559
'tags' => $this->tags,
546-
'source' => $source,
560+
'source' => $source, // @deprecated Can be removed in version 3.0.0.
547561
'is_read' => $this->isReadBy($context_user),
548562
'is_read_later' => $this->isInBookmarksOf($context_user),
549563
'collections' => array_column($this->collections(), 'id'),

0 commit comments

Comments
 (0)