refactor(api): extract inline-media hosting into a HostInlineMedia action
The download+host+422 orchestration was a private controller method doing IO and throwing — that's an operation, not a controller concern. Move it to App\Actions\Post\HostInlineMedia::execute() (alongside CreatePost/UpdatePost) so the controller stays thin and the logic is reusable/testable.
This commit is contained in:
parent
41cb9b02a3
commit
a6bb39cc1a
2 changed files with 45 additions and 29 deletions
42
app/Actions/Post/HostInlineMedia.php
Normal file
42
app/Actions/Post/HostInlineMedia.php
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Actions\Post;
|
||||
|
||||
use App\Enums\Media\Type as MediaType;
|
||||
use App\Models\Workspace;
|
||||
use App\Services\Post\MediaAttacher;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class HostInlineMedia
|
||||
{
|
||||
/**
|
||||
* Resolve a post's inline media into hosted media — external URLs are
|
||||
* downloaded and stored; items already on our disk pass through. Rejects
|
||||
* (422) when any URL can't be fetched, so a post is never persisted with
|
||||
* broken media.
|
||||
*
|
||||
* @param array<MediaType> $allowedTypes
|
||||
* @param array<int, array<string, mixed>> $media
|
||||
* @return array<int, array<string, mixed>>
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public static function execute(Workspace $workspace, array $allowedTypes, array $media): array
|
||||
{
|
||||
if ($media === []) {
|
||||
return $media;
|
||||
}
|
||||
|
||||
$result = app(MediaAttacher::class)->resolveInlineMedia($workspace, $allowedTypes, $media);
|
||||
|
||||
if ($result['failed'] !== []) {
|
||||
throw ValidationException::withMessages([
|
||||
'media' => ['Could not fetch media from URL: '.implode(', ', $result['failed'])],
|
||||
]);
|
||||
}
|
||||
|
||||
return $result['media'];
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
use App\Actions\Post\CreatePost;
|
||||
use App\Actions\Post\DeletePost;
|
||||
use App\Actions\Post\HostInlineMedia;
|
||||
use App\Actions\Post\UpdatePost;
|
||||
use App\Enums\Media\Type as MediaType;
|
||||
use App\Enums\Post\Action as PostAction;
|
||||
|
|
@ -18,7 +19,6 @@
|
|||
use App\Http\Resources\Api\PostPreviewResource;
|
||||
use App\Http\Resources\Api\PostResource;
|
||||
use App\Models\Post;
|
||||
use App\Models\Workspace;
|
||||
use App\Services\Post\MediaAttacher;
|
||||
use App\Support\PostStatusRules;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
|
@ -54,7 +54,7 @@ public function store(StorePostRequest $request): JsonResponse
|
|||
$data = $request->validated();
|
||||
|
||||
if (array_key_exists('media', $data)) {
|
||||
$data['media'] = $this->hostInlineMedia(
|
||||
$data['media'] = HostInlineMedia::execute(
|
||||
$workspace,
|
||||
Post::allowedMediaTypesFor($request->selectedPlatforms()),
|
||||
$data['media'],
|
||||
|
|
@ -77,7 +77,7 @@ public function update(UpdatePostRequest $request, Post $post): PostResource|Jso
|
|||
$data = $request->validated();
|
||||
|
||||
if (array_key_exists('media', $data)) {
|
||||
$data['media'] = $this->hostInlineMedia(
|
||||
$data['media'] = HostInlineMedia::execute(
|
||||
$request->user()->currentWorkspace,
|
||||
$post->allowedMediaTypes(),
|
||||
$data['media'],
|
||||
|
|
@ -99,32 +99,6 @@ public function update(UpdatePostRequest $request, Post $post): PostResource|Jso
|
|||
return new PostResource($updated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download and host external media URLs; reject (422) if one can't be fetched.
|
||||
*
|
||||
* @param array<MediaType> $allowedTypes
|
||||
* @param array<int, array<string, mixed>> $media
|
||||
* @return array<int, array<string, mixed>>
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function hostInlineMedia(Workspace $workspace, array $allowedTypes, array $media): array
|
||||
{
|
||||
if ($media === []) {
|
||||
return $media;
|
||||
}
|
||||
|
||||
$result = app(MediaAttacher::class)->resolveInlineMedia($workspace, $allowedTypes, $media);
|
||||
|
||||
if ($result['failed'] !== []) {
|
||||
throw ValidationException::withMessages([
|
||||
'media' => ['Could not fetch media from URL: '.implode(', ', $result['failed'])],
|
||||
]);
|
||||
}
|
||||
|
||||
return $result['media'];
|
||||
}
|
||||
|
||||
public function destroy(Request $request, Post $post): JsonResponse
|
||||
{
|
||||
$this->authorize('delete', $post);
|
||||
|
|
|
|||
Loading…
Reference in a new issue