From a6bb39cc1a03d5457ab43f7ed55892ba68039c9f Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Sun, 28 Jun 2026 21:15:01 -0300 Subject: [PATCH] refactor(api): extract inline-media hosting into a HostInlineMedia action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- app/Actions/Post/HostInlineMedia.php | 42 +++++++++++++++++++++ app/Http/Controllers/Api/PostController.php | 32 ++-------------- 2 files changed, 45 insertions(+), 29 deletions(-) create mode 100644 app/Actions/Post/HostInlineMedia.php diff --git a/app/Actions/Post/HostInlineMedia.php b/app/Actions/Post/HostInlineMedia.php new file mode 100644 index 00000000..3d0652c7 --- /dev/null +++ b/app/Actions/Post/HostInlineMedia.php @@ -0,0 +1,42 @@ + $allowedTypes + * @param array> $media + * @return array> + * + * @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']; + } +} diff --git a/app/Http/Controllers/Api/PostController.php b/app/Http/Controllers/Api/PostController.php index 3326c5fa..bd020741 100644 --- a/app/Http/Controllers/Api/PostController.php +++ b/app/Http/Controllers/Api/PostController.php @@ -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 $allowedTypes - * @param array> $media - * @return array> - * - * @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);