diff --git a/app/Http/Controllers/Forms/FormController.php b/app/Http/Controllers/Forms/FormController.php index b21c2170..a70ff511 100644 --- a/app/Http/Controllers/Forms/FormController.php +++ b/app/Http/Controllers/Forms/FormController.php @@ -121,8 +121,15 @@ class FormController extends Controller 'creator_id' => $request->user()->id, ])); + if ($this->formCleaner->hasCleaned()) { + $formStatus = $form->workspace->is_trialing ? 'Non-trial' : 'Pro'; + $message = 'Form successfully created, but the ' . $formStatus . ' features you used will be disabled when sharing your form:'; + } else { + $message = 'Form created.'; + } + return $this->success([ - 'message' => $this->formCleaner->hasCleaned() ? 'Form successfully created, but the Pro features you used will be disabled when sharing your form:' : 'Form created.' . ($form->visibility == 'draft' ? ' But other people won\'t be able to see the form since it\'s currently in draft mode' : ''), + 'message' => $message . ($form->visibility == 'draft' ? ' But other people won\'t be able to see the form since it\'s currently in draft mode' : ''), 'form' => (new FormResource($form))->setCleanings($this->formCleaner->getPerformedCleanings()), 'users_first_form' => $request->user()->forms()->count() == 1, ]); @@ -145,8 +152,16 @@ class FormController extends Controller $form->update($formData); + if ($this->formCleaner->hasCleaned()) { + $formSubscription = $form->is_pro ? 'Enterprise' : 'Pro'; + $formStatus = $form->workspace->is_trialing ? 'Non-trial' : $formSubscription; + $message = 'Form successfully updated, but the ' . $formStatus . ' features you used will be disabled when sharing your form.'; + } else { + $message = 'Form updated.'; + } + return $this->success([ - 'message' => $this->formCleaner->hasCleaned() ? 'Form successfully updated, but the Pro features you used will be disabled when sharing your form:' : 'Form updated.' . ($form->visibility == 'draft' ? ' But other people won\'t be able to see the form since it\'s currently in draft mode' : ''), + 'message' => $message . ($form->visibility == 'draft' ? ' But other people won\'t be able to see the form since it\'s currently in draft mode' : ''), 'form' => (new FormResource($form))->setCleanings($this->formCleaner->getPerformedCleanings()), ]); } diff --git a/app/Http/Resources/FormResource.php b/app/Http/Resources/FormResource.php index 5c453af6..00bc5f26 100644 --- a/app/Http/Resources/FormResource.php +++ b/app/Http/Resources/FormResource.php @@ -40,6 +40,7 @@ class FormResource extends JsonResource return array_merge(parent::toArray($request), $ownerData, [ 'is_pro' => $this->workspaceIsPro(), + 'is_trialing' => $this->workspaceIsTrialing(), 'workspace_id' => $this->workspace_id, 'workspace' => new WorkspaceResource($this->getWorkspace()), 'is_closed' => $this->is_closed, @@ -92,6 +93,11 @@ class FormResource extends JsonResource return $this->extra?->workspaceIsPro ?? $this->getWorkspace()->is_pro ?? $this->is_pro; } + private function workspaceIsTrialing() + { + return $this->getWorkspace()->is_trialing; + } + private function userIsFormOwner() { return $this->extra?->userIsOwner ?? diff --git a/app/Models/Workspace.php b/app/Models/Workspace.php index f4ecafc8..89c24ced 100644 --- a/app/Models/Workspace.php +++ b/app/Models/Workspace.php @@ -28,6 +28,7 @@ class Workspace extends Model implements CachableAttributes protected $appends = [ 'is_pro', + 'is_trialing', 'is_enterprise', ]; @@ -107,6 +108,24 @@ class Workspace extends Model implements CachableAttributes }); } + public function getIsTrialingAttribute() + { + if (is_null(config('cashier.key'))) { + return false; // If no paid plan so FALSE for ALL + } + + return $this->remember('is_trialing', 15 * 60, function (): bool { + // Make sure at least one owner is pro + foreach ($this->owners as $owner) { + if ($owner->onTrial()) { + return true; + } + } + + return false; + }); + } + public function getIsEnterpriseAttribute() { if (is_null(config('cashier.key'))) { diff --git a/app/Service/Forms/FormCleaner.php b/app/Service/Forms/FormCleaner.php index ebc2f3e6..3d350489 100644 --- a/app/Service/Forms/FormCleaner.php +++ b/app/Service/Forms/FormCleaner.php @@ -35,6 +35,10 @@ class FormCleaner 'seo_meta' => [], ]; + private array $formNonTrialingDefaults = [ + 'custom_code' => null, + ]; + private array $fieldDefaults = [ // 'name' => '' TODO: prevent name changing, use alias for column and keep original name as it is 'file_upload' => false, @@ -111,6 +115,10 @@ class FormCleaner return $workspace->is_pro; } + private function isTrialing(Workspace $workspace) + { + return $workspace->is_trialing; + } /** * Dry run celanings * @@ -118,6 +126,10 @@ class FormCleaner */ public function simulateCleaning(Workspace $workspace): FormCleaner { + if ($this->isTrialing($workspace)) { + $this->data = $this->removeNonTrialingFeatures($this->data, true); + } + if (!$this->isPro($workspace)) { $this->data = $this->removeProFeatures($this->data, true); } @@ -133,6 +145,10 @@ class FormCleaner */ public function performCleaning(Workspace $workspace): FormCleaner { + if ($this->isTrialing($workspace)) { + $this->data = $this->removeNonTrialingFeatures($this->data, true); + } + if (!$this->isPro($workspace)) { $this->data = $this->removeProFeatures($this->data); } @@ -155,6 +171,12 @@ class FormCleaner return $data; } + private function removeNonTrialingFeatures(array $data, $simulation = false) + { + $this->clean($data, $this->formNonTrialingDefaults); + return $data; + } + private function removeProFeatures(array $data, $simulation = false) { $this->cleanForm($data, $simulation); diff --git a/tests/Feature/Forms/FormTest.php b/tests/Feature/Forms/FormTest.php index 42c698c8..648f55fd 100644 --- a/tests/Feature/Forms/FormTest.php +++ b/tests/Feature/Forms/FormTest.php @@ -168,3 +168,26 @@ it('can create form with dark mode', function () { ->etc(); }); }); + +it('can create form with custom scripts', function () { + $user = $this->actingAsTrialingUser(); + $workspace = $this->createUserWorkspace($user); + $form = $this->createForm($user, $workspace, [ + 'custom_code' => "", + ]); + $formData = (new \App\Http\Resources\FormResource($form))->toArray(request()); + $this->postJson(route('open.forms.store', $formData)) + ->assertSuccessful() + ->assertJson([ + 'type' => 'success', + 'message' => 'Form successfully created, but the Non-trial features you used will be disabled when sharing your form:', + 'form' => ['custom_code' => null] + ]); + + $this->getJson(route('forms.show', $form->slug)) + ->assertSuccessful()->assertJson([ + 'id' => $form->id, + 'title' => $form->title, + 'custom_code' => null + ]); +}); diff --git a/tests/TestHelpers.php b/tests/TestHelpers.php index e1e0c317..9a551f7a 100644 --- a/tests/TestHelpers.php +++ b/tests/TestHelpers.php @@ -179,6 +179,21 @@ trait TestHelpers return $user; } + public function createTrialingUser() + { + $user = $this->createUser(); + $user->subscriptions()->create([ + 'name' => 'default', + 'stripe_id' => Str::random(), + 'stripe_status' => 'trialing', + 'stripe_price' => Str::random(), + 'trial_ends_at' => now()->addDays(5), + 'quantity' => 1, + ]); + + return $user; + } + public function actingAsUser(?User $user = null) { if ($user == null) { @@ -207,6 +222,15 @@ trait TestHelpers return $this->actingAsUser($user); } + public function actingAsTrialingUser(User $user = null) + { + if ($user == null) { + $user = $this->createTrialingUser(); + } + + return $this->actingAsUser($user); + } + public function actingAsGuest() { if (Auth::check()) {