* Remove the automations module Drops the visual workflow builder end to end: actions, node runners, commands, jobs, models, observers, policy, resources, requests, routes, broadcast channel, scheduler entries, Horizon supervisor, Vue pages and components, canvas undo/redo history, CodeEditor, translations, factories and tests. A new migration rewrites posts.created_via = 'automation' to 'web' and drops the five automation tables. The CreatedVia::Automation enum case is removed. The 2026-08-21 social-account identity migration now skips its automation node repointing when the automations table no longer exists, so it stays re-runnable after the drop. Orphaned dependencies removed: simplepie/simplepie, @vue-flow/*, codemirror and @codemirror/*. * Drop the orphaned common.beta translation key * Remove automation leftovers: ResolvableUrl rule, feed fixtures, useShortcut, nav badge * Drop the unused chart wrapper and @unovis packages * Address review: keep the shipped migration untouched, drop the dead previewOnly chain - Restore 2026_08_21 migration to exactly what production ran; the rehearsal test now recreates the automations table it expects instead. - Mark the drop migration's down() irreversible like its siblings. - Simplify DropAutomationTablesMigrationTest to the sibling shape. - Remove previewOnly / aiGenerateVariants: the only caller that set the prop was the deleted automation Generate node. - Run pint over lang/*/common.php after the beta key removal. * Exercise the drop migration against the real automation tables and their FKs * Drop DuplicateIdentityRehearsalTest: it re-ran a frozen migration that reads the removed automations table
78 lines
1.9 KiB
PHP
78 lines
1.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Observers;
|
|
|
|
use App\Enums\Post\Status as PostStatus;
|
|
use App\Events\OnboardingStatusUpdated;
|
|
use App\Events\PostCreated;
|
|
use App\Events\PostStatusChanged;
|
|
use App\Models\Account;
|
|
use App\Models\Post;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class PostObserver
|
|
{
|
|
public function created(Post $post): void
|
|
{
|
|
DB::afterCommit(fn () => PostCreated::dispatch($post));
|
|
|
|
$this->notifyOnboarding($post);
|
|
}
|
|
|
|
public function deleted(Post $post): void
|
|
{
|
|
$this->notifyOnboarding($post);
|
|
}
|
|
|
|
public function saved(Post $post): void
|
|
{
|
|
if (! $post->wasChanged('status')) {
|
|
return;
|
|
}
|
|
|
|
$previousStatus = $this->previousStatus($post);
|
|
|
|
DB::afterCommit(fn () => PostStatusChanged::dispatch($post, $previousStatus));
|
|
}
|
|
|
|
private function previousStatus(Post $post): ?PostStatus
|
|
{
|
|
$previous = $post->getRawOriginal('status');
|
|
|
|
if ($previous instanceof PostStatus) {
|
|
return $previous;
|
|
}
|
|
|
|
if (is_string($previous)) {
|
|
return PostStatus::tryFrom($previous);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Notify only on the account's first post create or last post delete —
|
|
* later creates / partial deletes would spam Echo while activation is open.
|
|
*/
|
|
private function notifyOnboarding(Post $post): void
|
|
{
|
|
$account = $post->workspace?->account;
|
|
|
|
if ($account?->isOnboardingOpen() && $this->otherPosts($account, $post)->doesntExist()) {
|
|
OnboardingStatusUpdated::dispatchForWorkspace($post->workspace_id, $post->user);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return Builder<Post>
|
|
*/
|
|
private function otherPosts(Account $account, Post $post): Builder
|
|
{
|
|
return Post::query()
|
|
->whereIn('workspace_id', $account->workspaces()->select('id'))
|
|
->whereKeyNot($post->id);
|
|
}
|
|
}
|