type === 'blog'; } public function publish(Post $post): PublishResult { if (! $post->title) { return PublishResult::rejected("Post {$post->id} has no title, required to publish to WordPress."); } $site = $post->site; if ($site->cms_type !== 'wordpress') { return PublishResult::rejected("Site '{$site->name}' is not configured as WordPress (cms_type={$site->cms_type})."); } if (! $site->wp_username || ! $site->wp_app_password) { return PublishResult::rejected("Site '{$site->name}' is missing WordPress credentials."); } $payload = [ 'title' => $post->title, 'content' => $post->body, 'status' => 'publish', ]; if ($post->image_url) { $mediaId = $this->uploadFeaturedImage($post, $site); if ($mediaId instanceof PublishResult) { return $mediaId; } $payload['featured_media'] = $mediaId; } try { $response = Http::withBasicAuth($site->wp_username, $site->wp_app_password) ->post(rtrim($site->url, '/').'/wp-json/wp/v2/posts', $payload); } catch (ConnectionException $e) { return PublishResult::failed("could not connect to site: {$e->getMessage()}"); } if ($response->failed()) { return PublishResult::failed($response->json('message') ?? 'unexpected response from WordPress'); } $link = $response->json('link'); if (! $link) { return PublishResult::failed('unexpected response from WordPress: missing post link'); } return PublishResult::success($link); } private function uploadFeaturedImage(Post $post, Site $site): int|PublishResult { try { $image = Http::get($post->image_url); } catch (ConnectionException $e) { return PublishResult::failed("could not download image: {$e->getMessage()}"); } if ($image->failed()) { return PublishResult::failed('could not download image: unexpected response from image URL'); } $filename = basename(parse_url($post->image_url, PHP_URL_PATH) ?: '') ?: 'image.jpg'; $contentType = $image->header('Content-Type') ?: 'application/octet-stream'; try { $response = Http::withBasicAuth($site->wp_username, $site->wp_app_password) ->withBody($image->body(), $contentType) ->withHeaders(['Content-Disposition' => "attachment; filename=\"{$filename}\""]) ->post(rtrim($site->url, '/').'/wp-json/wp/v2/media'); } catch (ConnectionException $e) { return PublishResult::failed("could not connect to site: {$e->getMessage()}"); } if ($response->failed()) { return PublishResult::failed($response->json('message') ?? 'unexpected response from WordPress while uploading the image'); } $mediaId = $response->json('id'); if (! $mediaId) { return PublishResult::failed('unexpected response from WordPress: missing media id'); } return $mediaId; } }