Skip to content

Commit 798d2d9

Browse files
committed
Improve pre-save check for link urls to properly check for trashed links (Kovah#1004)
1 parent 3592497 commit 798d2d9

10 files changed

Lines changed: 84 additions & 16 deletions

File tree

app/Http/Controllers/App/BookmarkletController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,11 @@ public function getLinkAddForm(Request $request)
3636

3737
session(['bookmarklet.create' => true]);
3838

39+
$existingLink = Link::withTrashed()->whereUrl($newUrl)->first();
40+
3941
return view('app.bookmarklet.create', [
40-
'existing_link' => Link::withTrashed()->whereUrl($newUrl)->first() ?: false,
42+
'existing_link' => $existingLink ?: false,
43+
'existing_deleted' => $existingLink?->trashed() ?? false,
4144
'bookmark_url' => $newUrl,
4245
'bookmark_title' => $newTitle,
4346
'bookmark_description' => $newDescription,

app/Http/Controllers/App/TrashController.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,20 @@ public function clearTrash(TrashClearRequest $request): RedirectResponse
4141

4242
public function restoreEntry(TrashRestoreRequest $request): RedirectResponse
4343
{
44-
TrashRepository::restore($request->input('model'), $request->input('id'));
44+
$model = TrashRepository::restore($request->input('model'), $request->input('id'));
4545

4646
flash(trans('trash.restore.' . $request->input('model')), 'success');
47+
48+
if ($request->boolean('redirect_to_model')) {
49+
return match ($request->input('model')) {
50+
'link' => redirect()->route('links.show', ['link' => $model]),
51+
'list' => redirect()->route('lists.show', ['list' => $model]),
52+
'tag' => redirect()->route('tags.show', ['tag' => $model]),
53+
'note' => redirect()->route('links.show', ['note' => $model->link()->first()]),
54+
default => redirect()->route('get-trash'),
55+
};
56+
}
57+
4758
return redirect()->route('get-trash');
4859
}
4960
}

app/Http/Controllers/FetchController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,17 @@ public function searchExistingUrls(Request $request): JsonResponse
6464
}
6565

6666
$link = Link::query()
67+
->withTrashed()
6768
->visibleForUser()
6869
->where('url', trim($query))
6970
->where('id', '!=', $request->input('ignore_id', 0))
7071
->first();
7172

7273
return response()->json([
73-
'linkFound' => $link !== null,
74+
'linkFound' => $link,
75+
'linkDeleted' => $link?->trashed(),
7476
'editLink' => $link ? route('links.edit', ['link' => $link]) : null,
77+
'restoreLink' => route('trash-restore'),
7578
]);
7679
}
7780

app/Http/Controllers/Models/LinkController.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public function create(): View
6363
return view('models.links.create', [
6464
'pageTitle' => trans('link.add'),
6565
'existing_link' => null,
66+
'existing_deleted' => false,
6667
'all_tags' => Tag::visibleForUser()->with('user:id,name')->get(['name', 'id', 'user_id']),
6768
'all_lists' => LinkList::visibleForUser()->with('user:id,name')->get(['name', 'id', 'user_id']),
6869
]);
@@ -130,6 +131,7 @@ public function edit(Link $link): View
130131
'pageTitle' => trans('link.edit') . ': ' . $link->shortTitle(),
131132
'link' => $link,
132133
'existing_link' => null,
134+
'existing_deleted' => null,
133135
'all_tags' => Tag::visibleForUser()->with('user:id,name')->get(['name', 'id', 'user_id']),
134136
'all_lists' => LinkList::visibleForUser()->with('user:id,name')->get(['name', 'id', 'user_id']),
135137
]);

app/Http/Requests/TrashRestoreRequest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ public function rules(): array
1717
'required',
1818
'numeric',
1919
],
20+
'redirect_to_model' => [
21+
'nullable',
22+
'boolean'
23+
]
2024
];
2125
}
2226
}

app/Repositories/TrashRepository.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use App\Models\LinkList;
77
use App\Models\Note;
88
use App\Models\Tag;
9+
use Illuminate\Database\Eloquent\Model;
910

1011
class TrashRepository
1112
{
@@ -47,9 +48,9 @@ public static function delete(string $model): bool
4748
*
4849
* @param string $model
4950
* @param int $id
50-
* @return bool
51+
* @return Link|Tag|LinkList|Note|null
5152
*/
52-
public static function restore(string $model, int $id): bool
53+
public static function restore(string $model, int $id): Link|Tag|LinkList|Note|null
5354
{
5455
$entry = match ($model) {
5556
'link' => Link::withTrashed()->byUser()->findOrFail($id),
@@ -61,6 +62,6 @@ public static function restore(string $model, int $id): bool
6162

6263
$entry?->restore();
6364

64-
return true;
65+
return $entry;
6566
}
6667
}

lang/en_US/trash.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
'deleted_notes' => 'Trashed notes',
1111

1212
'restore' => 'Restore entry',
13+
'restore_deleted_link' => 'Restore deleted Link',
1314

1415
'clear_trash' => 'Clear Trash',
1516
'delete_warning' => 'Permanently deleted entries can not be restored!',

resources/assets/js/components/UrlField.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ export default class UrlField {
88
this.$field = $el;
99

1010
this.$linkExistsWarning = document.querySelector('.link-exists');
11+
this.$linkExistsEdit = this.$linkExistsWarning.querySelector('.link-exists-edit');
12+
this.$linkExistsRestore = this.$linkExistsWarning.querySelector('.link-exists-restore');
13+
this.$linkExistsRestoreId = document.querySelector('.link-exists-restore-id');
1114

1215
if (!this.$linkExistsWarning) {
1316
return;
@@ -52,12 +55,24 @@ export default class UrlField {
5255
}).then((result) => {
5356

5457
// If the link already exist, mark the field as invalid
55-
if (result.linkFound === true) {
58+
if (result.linkFound !== null) {
59+
60+
if (result.linkDeleted === true) {
61+
this.$linkExistsEdit.classList.add('d-none');
62+
this.$linkExistsRestore.classList.remove('d-none');
63+
this.$linkExistsRestoreId.value = result.linkFound.id;
64+
} else {
65+
this.$linkExistsRestore.classList.add('d-none');
66+
this.$linkExistsLink.href = result.editLink;
67+
this.$linkExistsEdit.classList.remove('d-none')
68+
}
5669
this.$field.classList.add('is-invalid');
57-
this.$linkExistsLink.href = result.editLink;
5870
this.$linkExistsWarning.classList.remove('d-none');
71+
5972
} else {
6073
this.$field.classList.remove('is-invalid');
74+
this.$linkExistsEdit.classList.add('d-none');
75+
this.$linkExistsRestore.classList.add('d-none');
6176
this.$linkExistsWarning.classList.add('d-none');
6277
this.$linkExistsLink.href = '';
6378
this.querySiteForMetaTags(url);

resources/views/models/links/edit.blade.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,18 @@ class="edit-form link-form">
2121
class="form-control form-control-lg{{ $errors->has('url') ? ' is-invalid' : '' }}"
2222
placeholder="@lang('placeholder.link_url')" value="{{ old('url') ?: $link->url }}"
2323
required autofocus>
24-
<p class="invalid-feedback link-exists {{ $existing_link ? '' : 'd-none' }}">
25-
@lang('link.existing_found')
26-
<a href="{{ route('links.edit', [$existing_link->id ?? 0]) }}">@lang('link.edit')</a>
27-
</p>
24+
25+
<div class="invalid-feedback link-exists d-flex align-items-center gap-2 {{ $existing_link ? '' : 'd-none' }}">
26+
<div>@lang('link.existing_found')</div>
27+
<a href="{{ route('links.edit', [$existing_link->id ?? 0]) }}"
28+
class="link-exists-edit {{ $existing_link && $existing_deleted ? 'd-none' : '' }}">@lang('link.edit')</a>
29+
30+
<button type="submit" form="exiting-link-restore" title="@lang('trash.restore')"
31+
class="link-exists-restore btn btn-sm btn-link {{ $existing_link && $existing_deleted ? '' : 'd-none' }}" >
32+
@lang('trash.restore_deleted_link')
33+
</button>
34+
</div>
35+
2836
@if ($errors->has('url'))
2937
<p class="invalid-feedback" role="alert">
3038
{{ $errors->first('url') }}
@@ -121,4 +129,11 @@ class="tag-select" data-tag-data="{{ $all_tags->toJson() }}"
121129
@method('DELETE')
122130
</form>
123131

132+
<form action="{{ route('trash-restore') }}" method="post" id="exiting-link-restore">
133+
@csrf
134+
<input type="hidden" name="model" value="link">
135+
<input type="hidden" name="redirect_to_model" value="1">
136+
<input type="hidden" name="id" class="link-exists-restore-id" value="{{ $existing_link->id ?? 0 }}">
137+
</form>
138+
124139
@endsection

resources/views/models/links/partials/create-form.blade.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,16 @@ class="form-control form-control-lg{{ $errors->has('url') || $existing_link ? '
1414
placeholder="@lang('placeholder.link_url')" value="{{ old('url') ?: $bookmark_url ?? '' }}"
1515
required autofocus>
1616

17-
<p class="invalid-feedback link-exists {{ $existing_link ? '' : 'd-none' }}">
18-
@lang('link.existing_found')
19-
<a href="{{ route('links.edit', [$existing_link->id ?? 0]) }}">@lang('link.edit')</a>
20-
</p>
17+
<div class="invalid-feedback link-exists d-flex align-items-center gap-2 {{ $existing_link ? '' : 'd-none' }}">
18+
<div>@lang('link.existing_found')</div>
19+
<a href="{{ route('links.edit', [$existing_link->id ?? 0]) }}"
20+
class="link-exists-edit {{ $existing_link && $existing_deleted ? 'd-none' : '' }}">@lang('link.edit')</a>
21+
22+
<button type="submit" form="exiting-link-restore" title="@lang('trash.restore')"
23+
class="link-exists-restore btn btn-sm btn-link {{ $existing_link && $existing_deleted ? '' : 'd-none' }}" >
24+
@lang('trash.restore_deleted_link')
25+
</button>
26+
</div>
2127

2228
@error('url')
2329
<p class="invalid-feedback" role="alert">
@@ -115,5 +121,12 @@ class="tag-select" data-tag-data="{{ $all_tags->toJson() }}"
115121

116122
</form>
117123

124+
<form action="{{ route('trash-restore') }}" method="post" id="exiting-link-restore">
125+
@csrf
126+
<input type="hidden" name="model" value="link">
127+
<input type="hidden" name="redirect_to_model" value="1">
128+
<input type="hidden" name="id" class="link-exists-restore-id" value="{{ $existing_link->id ?? 0 }}">
129+
</form>
130+
118131
</div>
119132
</div>

0 commit comments

Comments
 (0)