Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
6e96ca8304 |
|||
|
cc2ff2b2a2 |
|||
|
73b9668088 |
|||
|
e8f2535cd1 |
|||
|
5481956d78 |
|||
|
7ce256baa5 |
10 changed files with 110 additions and 7 deletions
|
|
@ -25,7 +25,7 @@ class Bookmark extends Model
|
||||||
return $this->belongsToMany('App\Models\Tag');
|
return $this->belongsToMany('App\Models\Tag');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function localUri(): Attribute
|
protected function uri(): Attribute
|
||||||
{
|
{
|
||||||
return Attribute::get(
|
return Attribute::get(
|
||||||
get: fn () => config('app.url').'/bookmarks/'.$this->id,
|
get: fn () => config('app.url').'/bookmarks/'.$this->id,
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,13 @@ class Like extends Model
|
||||||
use FilterHtml;
|
use FilterHtml;
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
|
protected function uri(): Attribute
|
||||||
|
{
|
||||||
|
return Attribute::get(
|
||||||
|
get: fn () => config('app.url').'/likes/'.$this->id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
protected function url(): Attribute
|
protected function url(): Attribute
|
||||||
{
|
{
|
||||||
return Attribute::set(
|
return Attribute::set(
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ class EntryHandler implements MicropubHandlerInterface
|
||||||
|
|
||||||
$dataArray = $data->toArray();
|
$dataArray = $data->toArray();
|
||||||
$location = match (true) {
|
$location = match (true) {
|
||||||
isset($dataArray['like-of']) => resolve(LikeService::class)->create($dataArray)->url,
|
isset($dataArray['like-of']) => resolve(LikeService::class)->create($dataArray)->uri,
|
||||||
isset($dataArray['bookmark-of']) => resolve(BookmarkService::class)->create($dataArray)->uri,
|
isset($dataArray['bookmark-of']) => resolve(BookmarkService::class)->create($dataArray)->uri,
|
||||||
isset($dataArray['name']) => resolve(ArticleService::class)->create($dataArray)->uri,
|
isset($dataArray['name']) => resolve(ArticleService::class)->create($dataArray)->uri,
|
||||||
default => resolve(NoteService::class)->create($dataArray)->uri,
|
default => resolve(NoteService::class)->create($dataArray)->uri,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('notes', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('shorturl');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('notes', function (Blueprint $table) {
|
||||||
|
$table->string('shorturl', 20)->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
</blockquote>
|
</blockquote>
|
||||||
@endisset
|
@endisset
|
||||||
<div>
|
<div>
|
||||||
<a href="/likes/{{ $like->id }}"><time class="dt-published" datetime="{{ $like->updated_at->toISO8601String() }}" title="{{ $like->updated_at->toISO8601String() }}">{{ $like->updated_at->diffForHumans() }}</time></a>
|
<a href="{{ $like->uri }}"><time class="dt-published" datetime="{{ $like->updated_at->toISO8601String() }}" title="{{ $like->updated_at->toISO8601String() }}">{{ $like->updated_at->diffForHumans() }}</time></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -211,14 +211,14 @@ Route::get('note/{id}', [NotesController::class, 'redirect']); // for legacy not
|
||||||
// Likes
|
// Likes
|
||||||
Route::prefix('likes')->group(function () {
|
Route::prefix('likes')->group(function () {
|
||||||
Route::get('/', [LikesController::class, 'index']);
|
Route::get('/', [LikesController::class, 'index']);
|
||||||
Route::get('/{like}', [LikesController::class, 'show']);
|
Route::get('/{like}', [LikesController::class, 'show'])->whereNumber('like');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Bookmarks
|
// Bookmarks
|
||||||
Route::prefix('bookmarks')->group(function () {
|
Route::prefix('bookmarks')->group(function () {
|
||||||
Route::get('/', [BookmarksController::class, 'index']);
|
Route::get('/', [BookmarksController::class, 'index']);
|
||||||
Route::redirect('/tagged', '/bookmarks');
|
Route::redirect('/tagged', '/bookmarks');
|
||||||
Route::get('/{bookmark}', [BookmarksController::class, 'show']);
|
Route::get('/{bookmark}', [BookmarksController::class, 'show'])->whereNumber('bookmark');
|
||||||
Route::get('/tagged/{tag}', [BookmarksController::class, 'tagged']);
|
Route::get('/tagged/{tag}', [BookmarksController::class, 'tagged']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,13 @@ class BookmarksTest extends TestCase
|
||||||
$response->assertViewIs('bookmarks.show');
|
$response->assertViewIs('bookmarks.show');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Test]
|
||||||
|
public function non_numeric_bookmark_id_gives_not_found_response(): void
|
||||||
|
{
|
||||||
|
$response = $this->get('/bookmarks/twcamp^share|twsrc^ios');
|
||||||
|
$response->assertNotFound();
|
||||||
|
}
|
||||||
|
|
||||||
#[Test]
|
#[Test]
|
||||||
public function when_bookmark_is_added_using_http_syntax_check_job_to_take_screenshot_is_invoked(): void
|
public function when_bookmark_is_added_using_http_syntax_check_job_to_take_screenshot_is_invoked(): void
|
||||||
{
|
{
|
||||||
|
|
@ -85,10 +92,10 @@ class BookmarksTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
#[Test]
|
||||||
public function bookmark_local_uri_attribute_returns_correct_url(): void
|
public function bookmark_uri_attribute_returns_correct_url(): void
|
||||||
{
|
{
|
||||||
$bookmark = Bookmark::factory()->create();
|
$bookmark = Bookmark::factory()->create();
|
||||||
$this->assertEquals(config('app.url').'/bookmarks/'.$bookmark->id, $bookmark->local_uri);
|
$this->assertEquals(config('app.url').'/bookmarks/'.$bookmark->id, $bookmark->uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
#[Test]
|
||||||
|
|
|
||||||
|
|
@ -178,4 +178,11 @@ class LikesTest extends TestCase
|
||||||
$response = $this->get('/likes/202');
|
$response = $this->get('/likes/202');
|
||||||
$response->assertNotFound();
|
$response->assertNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Test]
|
||||||
|
public function non_numeric_like_id_gives_not_found_response(): void
|
||||||
|
{
|
||||||
|
$response = $this->get('/likes/twcamp^share|twsrc^ios');
|
||||||
|
$response->assertNotFound();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ use App\Jobs\SendWebMentions;
|
||||||
use App\Jobs\SyndicateNoteToBluesky;
|
use App\Jobs\SyndicateNoteToBluesky;
|
||||||
use App\Jobs\SyndicateNoteToMastodon;
|
use App\Jobs\SyndicateNoteToMastodon;
|
||||||
use App\Models\Article;
|
use App\Models\Article;
|
||||||
|
use App\Models\Bookmark;
|
||||||
|
use App\Models\Like;
|
||||||
use App\Models\Media;
|
use App\Models\Media;
|
||||||
use App\Models\Note;
|
use App\Models\Note;
|
||||||
use App\Models\Place;
|
use App\Models\Place;
|
||||||
|
|
@ -879,6 +881,50 @@ class MicropubControllerTest extends TestCase
|
||||||
$this->assertStringStartsWith(config('app.url').'/blog/', $response->headers->get('Location'));
|
$this->assertStringStartsWith(config('app.url').'/blog/', $response->headers->get('Location'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Test]
|
||||||
|
public function micropub_client_api_request_for_a_like_returns_our_permalink_in_the_location_header(): void
|
||||||
|
{
|
||||||
|
Queue::fake();
|
||||||
|
|
||||||
|
$response = $this->postJson(
|
||||||
|
'/api/post',
|
||||||
|
[
|
||||||
|
'type' => ['h-entry'],
|
||||||
|
'properties' => [
|
||||||
|
'like-of' => ['https://example.org/liked-post'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
['HTTP_Authorization' => 'Bearer '.$this->getToken()]
|
||||||
|
);
|
||||||
|
|
||||||
|
$like = Like::where('url', 'https://example.org/liked-post')->sole();
|
||||||
|
$response
|
||||||
|
->assertStatus(201)
|
||||||
|
->assertHeader('Location', config('app.url').'/likes/'.$like->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Test]
|
||||||
|
public function micropub_client_api_request_for_a_bookmark_returns_our_permalink_in_the_location_header(): void
|
||||||
|
{
|
||||||
|
Queue::fake();
|
||||||
|
|
||||||
|
$response = $this->postJson(
|
||||||
|
'/api/post',
|
||||||
|
[
|
||||||
|
'type' => ['h-entry'],
|
||||||
|
'properties' => [
|
||||||
|
'bookmark-of' => ['https://example.org/bookmarked-page'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
['HTTP_Authorization' => 'Bearer '.$this->getToken()]
|
||||||
|
);
|
||||||
|
|
||||||
|
$bookmark = Bookmark::where('url', 'https://example.org/bookmarked-page')->sole();
|
||||||
|
$response
|
||||||
|
->assertStatus(201)
|
||||||
|
->assertHeader('Location', config('app.url').'/bookmarks/'.$bookmark->id);
|
||||||
|
}
|
||||||
|
|
||||||
#[Test]
|
#[Test]
|
||||||
public function micropub_client_api_request_creates_an_unpublished_article_when_post_status_is_draft(): void
|
public function micropub_client_api_request_creates_an_unpublished_article_when_post_status_is_draft(): void
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,14 @@ class LikesTest extends TestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
#[Test]
|
||||||
|
public function like_uri_attribute_returns_our_permalink(): void
|
||||||
|
{
|
||||||
|
$like = Like::factory()->create();
|
||||||
|
|
||||||
|
$this->assertEquals(config('app.url').'/likes/'.$like->id, $like->uri);
|
||||||
|
}
|
||||||
|
|
||||||
#[Test]
|
#[Test]
|
||||||
public function we_can_set_the_author_url(): void
|
public function we_can_set_the_author_url(): void
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue