diff --git a/app/Actions/Post/CreatePost.php b/app/Actions/Post/CreatePost.php index 1462f425..85adfb06 100644 --- a/app/Actions/Post/CreatePost.php +++ b/app/Actions/Post/CreatePost.php @@ -12,7 +12,6 @@ use App\Models\Workspace; use Carbon\Carbon; use Illuminate\Support\Facades\DB; -use InvalidArgumentException; class CreatePost { @@ -29,37 +28,30 @@ class CreatePost * works for REST, MCP, and web callers. * * `created_via` records which entry point created the post (web, mcp, - * api, or automation). Callers must set it explicitly. + * api, or automation). Analytical only — defaults to web when omitted + * or invalid, and never blocks creation. * * @param array{ * content?: ?string, * media?: array, * date?: ?string, * scheduled_at?: ?string, - * created_via: CreatedVia, + * created_via?: CreatedVia, * platforms?: array}>, * label_ids?: array * } $data - * - * @throws InvalidArgumentException when created_via is missing or not a CreatedVia case */ public static function execute(Workspace $workspace, User $user, array $data): Post { - $createdVia = data_get($data, 'created_via'); - - if (! $createdVia instanceof CreatedVia) { - throw new InvalidArgumentException('created_via must be a CreatedVia enum case.'); - } - $scheduledAt = self::resolveScheduledAt($data); - $post = DB::transaction(function () use ($workspace, $user, $data, $scheduledAt, $createdVia): Post { + $post = DB::transaction(function () use ($workspace, $user, $data, $scheduledAt): Post { $post = $workspace->posts()->create([ 'user_id' => $user->id, 'content' => data_get($data, 'content', ''), 'media' => data_get($data, 'media', []), 'status' => PostStatus::Draft, - 'created_via' => $createdVia, + 'created_via' => self::resolveCreatedVia($data), 'scheduled_at' => $scheduledAt, ]); @@ -105,6 +97,26 @@ public static function execute(Workspace $workspace, User $user, array $data): P return $post; } + /** + * Analytical only — never fail creation over a missing/invalid value. + * + * @param array $data + */ + private static function resolveCreatedVia(array $data): CreatedVia + { + $value = data_get($data, 'created_via'); + + if ($value instanceof CreatedVia) { + return $value; + } + + if (is_string($value)) { + return CreatedVia::tryFrom($value) ?? CreatedVia::Web; + } + + return CreatedVia::Web; + } + /** * @param array $data */ diff --git a/tests/Feature/Actions/Post/CreatePostTest.php b/tests/Feature/Actions/Post/CreatePostTest.php index e0d2d7f4..20b68490 100644 --- a/tests/Feature/Actions/Post/CreatePostTest.php +++ b/tests/Feature/Actions/Post/CreatePostTest.php @@ -44,11 +44,29 @@ 'automation' => CreatedVia::Automation, ]); -test('execute requires created_via', function () { +test('execute defaults created_via to web when omitted', function () { $user = User::factory()->create(); $workspace = Workspace::factory()->create(['user_id' => $user->id]); - CreatePost::execute($workspace, $user, [ + $post = CreatePost::execute($workspace, $user, [ 'content' => 'Hello world', ]); -})->throws(InvalidArgumentException::class, 'created_via must be a CreatedVia enum case.'); + + expect($post->fresh()->created_via)->toBe(CreatedVia::Web); +}); + +test('execute defaults created_via to web when null or invalid', function (mixed $createdVia) { + $user = User::factory()->create(); + $workspace = Workspace::factory()->create(['user_id' => $user->id]); + + $post = CreatePost::execute($workspace, $user, [ + 'content' => 'Hello world', + 'created_via' => $createdVia, + ]); + + expect($post->fresh()->created_via)->toBe(CreatedVia::Web); +})->with([ + 'null' => null, + 'invalid string' => 'not-a-channel', + 'integer' => 1, +]);