Compare commits

..
6 changed files with 6 additions and 129 deletions

View file

@ -70,9 +70,7 @@ class MicropubController extends Controller
'error' => 'invalid_request', 'error' => 'invalid_request',
'error_description' => 'No known note with given ID', 'error_description' => 'No known note with given ID',
], 404); ], 404);
} catch (MicropubUnsupportedModelException $e) { } catch (MicropubUnsupportedModelException) {
report($e);
return response()->json([ return response()->json([
'error' => 'invalid', 'error' => 'invalid',
'error_description' => 'This implementation currently only supports the updating of notes', 'error_description' => 'This implementation currently only supports the updating of notes',
@ -82,16 +80,12 @@ class MicropubController extends Controller
'error' => 'invalid_request', 'error' => 'invalid_request',
'error_description' => $e->getMessage(), 'error_description' => $e->getMessage(),
], 400); ], 400);
} catch (MicropubHandlerException $e) { } catch (MicropubHandlerException) {
report($e);
return response()->json([ return response()->json([
'error' => 'unsupported_operation', 'error' => 'unsupported_operation',
'error_description' => 'The request could not be processed by this server', 'error_description' => 'The request could not be processed by this server',
], 500); ], 500);
} catch (\Throwable $e) { } catch (\Exception $e) {
report($e);
return response()->json([ return response()->json([
'error' => 'server_error', 'error' => 'server_error',
'error_description' => 'An error occurred processing the request', 'error_description' => 'An error occurred processing the request',

View file

@ -40,7 +40,6 @@ class Article extends Model
return [ return [
'titleurl' => [ 'titleurl' => [
'source' => 'title', 'source' => 'title',
'includeTrashed' => true,
], ],
]; ];
} }
@ -94,13 +93,6 @@ class Article extends Model
); );
} }
protected function uri(): Attribute
{
return Attribute::get(
get: fn () => config('app.url').$this->link,
);
}
/** /**
* Scope a query to only include articles from a particular year/month. * Scope a query to only include articles from a particular year/month.
*/ */

View file

@ -8,29 +8,12 @@ use App\Models\Article;
class ArticleService class ArticleService
{ {
/**
* @throws \InvalidArgumentException if a published article already has this title
*/
public function create(array $data): Article public function create(array $data): Article
{ {
$attributes = [ return Article::create([
'title' => $data['name'], 'title' => $data['name'],
'main' => $data['content'], 'main' => $data['content'],
'published' => ($data['post-status'] ?? null) !== 'draft', 'published' => ($data['post-status'] ?? null) !== 'draft',
]; ]);
$existing = Article::where('title', $data['name'])->first();
if ($existing !== null) {
if ($existing->published) {
throw new \InvalidArgumentException("An article titled \"{$data['name']}\" has already been published");
}
$existing->update($attributes);
return $existing;
}
return Article::create($attributes);
} }
} }

View file

@ -37,7 +37,7 @@ class EntryHandler implements MicropubHandlerInterface
$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)->url,
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)->link,
default => resolve(NoteService::class)->create($dataArray)->uri, default => resolve(NoteService::class)->create($dataArray)->uri,
}; };

View file

@ -4,17 +4,14 @@ declare(strict_types=1);
namespace Tests\Feature; namespace Tests\Feature;
use App\Exceptions\MicropubHandlerException;
use App\Jobs\SendWebMentions; 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\Media; use App\Models\Media;
use App\Models\Note; use App\Models\Note;
use App\Models\Place; use App\Models\Place;
use App\Models\SyndicationTarget; use App\Models\SyndicationTarget;
use Faker\Factory; use Faker\Factory;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Queue;
@ -460,11 +457,6 @@ class MicropubControllerTest extends TestCase
#[Test] #[Test]
public function micropub_client_api_request_for_unsupported_post_type_returns_error(): void public function micropub_client_api_request_for_unsupported_post_type_returns_error(): void
{ {
$this->mock(ExceptionHandler::class)
->shouldReceive('report')
->once()
->with(\Mockery::type(MicropubHandlerException::class));
$response = $this->postJson( $response = $this->postJson(
'/api/post', '/api/post',
[ [
@ -879,8 +871,6 @@ class MicropubControllerTest extends TestCase
'main' => $content, 'main' => $content,
'published' => true, 'published' => true,
]); ]);
$response->assertHeader('Location');
$this->assertStringStartsWith(config('app.url').'/blog/', $response->headers->get('Location'));
} }
#[Test] #[Test]
@ -912,64 +902,4 @@ class MicropubControllerTest extends TestCase
'published' => false, 'published' => false,
]); ]);
} }
#[Test]
public function micropub_client_api_request_updates_an_existing_draft_article_with_the_same_name(): void
{
$draft = Article::create([
'title' => 'WireGuard',
'main' => 'Early draft content',
'published' => false,
]);
$response = $this->postJson(
'/api/post',
[
'type' => ['h-entry'],
'properties' => [
'name' => ['WireGuard'],
'content' => ['Finished content'],
],
],
['HTTP_Authorization' => 'Bearer '.$this->getToken()]
);
$response
->assertJson(['response' => 'created'])
->assertStatus(201);
$this->assertSame(1, Article::where('title', 'WireGuard')->count());
$this->assertDatabaseHas('articles', [
'id' => $draft->id,
'title' => 'WireGuard',
'main' => 'Finished content',
'published' => true,
]);
}
#[Test]
public function micropub_client_api_request_errors_when_an_article_with_the_same_name_is_already_published(): void
{
Article::create([
'title' => 'WireGuard',
'main' => 'Published content',
'published' => true,
]);
$response = $this->postJson(
'/api/post',
[
'type' => ['h-entry'],
'properties' => [
'name' => ['WireGuard'],
'content' => ['Some other content'],
],
],
['HTTP_Authorization' => 'Bearer '.$this->getToken()]
);
$response
->assertJson(['error' => 'invalid_request'])
->assertStatus(400);
$this->assertSame(1, Article::where('title', 'WireGuard')->count());
}
} }

View file

@ -63,28 +63,6 @@ class ArticlesTest extends TestCase
); );
} }
#[Test]
public function uri_is_the_absolute_form_of_the_link(): void
{
$article = Article::create([
'title' => 'Test',
'main' => 'Test',
]);
$this->assertEquals(config('app.url').$article->link, $article->uri);
}
#[Test]
public function slug_is_suffixed_when_a_trashed_article_already_used_it(): void
{
$original = Article::create(['title' => 'My Title', 'main' => 'Content']);
$original->delete();
$newArticle = Article::create(['title' => 'My Title', 'main' => 'Other content']);
$this->assertEquals('my-title-2', $newArticle->titleurl);
}
#[Test] #[Test]
public function date_scope_returns_expected_articles(): void public function date_scope_returns_expected_articles(): void
{ {