From 62971a2ef4e46466da4a4d5377160963c33275e5 Mon Sep 17 00:00:00 2001 From: Julien Nahum Date: Fri, 23 Feb 2024 11:54:12 +0100 Subject: [PATCH] Lint PHP code psr-12, add GH action --- .github/workflows/laravel.yml | 43 +- app/Console/Commands/CleanDatabase.php | 16 +- app/Console/Commands/GenerateTemplate.php | 84 ++-- .../Commands/Tax/GenerateTaxExport.php | 91 ++-- app/Console/Kernel.php | 1 - app/Events/Forms/FormSubmitted.php | 9 +- app/Events/Models/FormCreated.php | 11 +- app/Exceptions/Handler.php | 5 +- app/Exceptions/VerifyEmailException.php | 2 +- .../Workspaces/WorkspaceAlreadyExisting.php | 2 +- app/Exports/FormSubmissionExport.php | 5 +- app/Exports/Tax/ArrayExport.php | 1 - .../Admin/ImpersonationController.php | 15 +- .../Auth/AppSumoAuthController.php | 25 +- .../Auth/ForgotPasswordController.php | 2 - app/Http/Controllers/Auth/LoginController.php | 5 - app/Http/Controllers/Auth/OAuthController.php | 14 +- .../Controllers/Auth/RegisterController.php | 18 +- .../Auth/ResetPasswordController.php | 2 - app/Http/Controllers/Auth/UserController.php | 9 +- .../Auth/VerificationController.php | 4 +- app/Http/Controllers/CaddyController.php | 11 +- .../Content/ChangelogController.php | 6 +- .../Content/FileUploadController.php | 3 +- .../Content/SignedStorageUrlController.php | 6 +- app/Http/Controllers/Controller.php | 8 +- .../Controllers/Forms/AiFormController.php | 8 +- app/Http/Controllers/Forms/FormController.php | 63 +-- .../Controllers/Forms/FormStatsController.php | 15 +- .../Forms/FormSubmissionController.php | 27 +- .../FormZapierWebhookController.php | 17 +- .../Forms/PublicFormController.php | 33 +- .../Controllers/Forms/RecordController.php | 3 +- .../Settings/PasswordController.php | 1 - .../Settings/ProfileController.php | 1 - app/Http/Controllers/SitemapController.php | 10 +- .../Controllers/SubscriptionController.php | 22 +- app/Http/Controllers/TemplateController.php | 29 +- .../Controllers/Webhook/AppSumoController.php | 9 +- .../Controllers/Webhook/StripeController.php | 8 +- app/Http/Controllers/WorkspaceController.php | 15 +- app/Http/Kernel.php | 4 +- app/Http/Middleware/AcceptsJsonMiddleware.php | 1 - app/Http/Middleware/AuthenticateJWT.php | 9 +- .../Middleware/CaddyRequestMiddleware.php | 6 +- .../Middleware/CustomDomainRestriction.php | 10 +- app/Http/Middleware/Form/ProForm.php | 2 +- app/Http/Middleware/Form/ProtectedForm.php | 13 +- .../Middleware/Form/ResolveFormMiddleware.php | 8 +- .../Middleware/ImpersonationMiddleware.php | 20 +- app/Http/Middleware/IsAdmin.php | 5 +- app/Http/Middleware/IsModerator.php | 5 +- app/Http/Middleware/IsNotSubscribed.php | 3 +- app/Http/Middleware/IsSubscribed.php | 5 +- .../Middleware/RedirectIfAuthenticated.php | 2 - app/Http/Middleware/SetLocale.php | 3 +- app/Http/Middleware/TrimStrings.php | 3 +- app/Http/Middleware/VerifyCsrfToken.php | 2 +- app/Http/Requests/AiGenerateFormRequest.php | 2 +- app/Http/Requests/AnswerFormRequest.php | 76 +-- .../StoreFormZapierWebhookRequest.php | 6 +- app/Http/Requests/StoreFormRequest.php | 3 - .../Templates/FormTemplateRequest.php | 7 +- app/Http/Requests/UpdateFormRequest.php | 1 - app/Http/Requests/UploadAssetRequest.php | 4 +- app/Http/Requests/UserFormRequest.php | 21 +- .../Workspace/CustomDomainRequest.php | 23 +- app/Http/Resources/FormResource.php | 14 +- app/Http/Resources/FormSubmissionResource.php | 8 +- app/Http/Resources/FormTemplateResource.php | 2 +- app/Http/Resources/UserResource.php | 2 +- app/Http/Resources/WorkspaceResource.php | 3 +- app/Jobs/Form/GenerateAiForm.php | 18 +- app/Jobs/Form/StoreFormSubmissionJob.php | 43 +- app/Listeners/FailedWebhookListener.php | 9 +- .../Forms/FormCreationConfirmation.php | 2 - app/Listeners/Forms/NotifyFormSubmission.php | 19 +- .../Forms/SubmissionConfirmation.php | 35 +- .../Forms/FormCreationConfirmationMail.php | 10 +- app/Mail/Forms/SubmissionConfirmationMail.php | 18 +- app/Mail/OpenFormMail.php | 4 +- app/Models/Forms/AI/AiFormCompletion.php | 15 +- app/Models/Forms/Form.php | 57 ++- app/Models/Forms/FormStatistic.php | 6 +- app/Models/Forms/FormSubmission.php | 8 +- app/Models/Forms/FormView.php | 4 +- app/Models/Integration/FormZapierWebhook.php | 6 +- app/Models/License.php | 8 +- app/Models/Template.php | 11 +- app/Models/Traits/CachableAttributes.php | 11 - app/Models/Traits/CachesAttributes.php | 2 +- app/Models/User.php | 23 +- app/Models/Workspace.php | 43 +- .../Forms/FailedWebhookNotification.php | 10 +- .../Forms/FormSubmissionNotification.php | 15 +- app/Notifications/ResetPassword.php | 2 +- .../FailedPaymentNotification.php | 2 +- app/Notifications/VerifyEmail.php | 4 +- app/Policies/FormPolicy.php | 12 - app/Policies/TemplatePolicy.php | 5 - app/Policies/WorkspacePolicy.php | 16 +- app/Providers/AppServiceProvider.php | 9 +- app/Providers/AuthServiceProvider.php | 2 - app/Providers/EventServiceProvider.php | 8 +- app/Providers/HorizonServiceProvider.php | 2 +- app/Providers/ModelStatsServiceProvider.php | 2 - app/Providers/RouteServiceProvider.php | 3 +- app/Rules/FormPropertyLogicRule.php | 303 ++++++------ app/Rules/OneEmailPerLine.php | 7 +- app/Rules/StorageFile.php | 19 +- app/Rules/ValidHCaptcha.php | 7 +- app/Rules/ValidPhoneInputRule.php | 7 +- app/Service/Forms/FormCleaner.php | 49 +- .../Forms/FormLogicConditionChecker.php | 446 ++++++++++-------- .../Forms/FormLogicPropertyResolver.php | 15 +- app/Service/Forms/FormSubmissionFormatter.php | 67 +-- .../Forms/Webhooks/AbstractWebhookHandler.php | 16 +- app/Service/Forms/Webhooks/DiscordHandler.php | 57 ++- .../Forms/Webhooks/SimpleWebhookHandler.php | 5 +- app/Service/Forms/Webhooks/SlackHandler.php | 45 +- .../Forms/Webhooks/WebhookHandlerProvider.php | 12 +- app/Service/Forms/Webhooks/ZapierHandler.php | 2 +- .../HTMLPurifier_URIScheme_notion.php | 7 +- app/Service/OpenAi/GptCompleter.php | 36 +- app/Service/OpenAi/Utils/JsonFixer.php | 37 +- app/Service/OpenAi/Utils/PadsJson.php | 22 +- app/Service/SeoMetaResolver.php | 40 +- app/Service/Storage/StorageFileNameParser.php | 13 +- app/Service/WorkspaceHelper.php | 3 - app/helpers.php | 4 +- composer.json | 1 + composer.lock | 68 ++- config/custom-domains.php | 4 +- config/excel.php | 106 ++--- config/links.php | 2 +- config/model-stats.php | 2 +- config/opnform.php | 8 +- config/pricing.php | 10 +- config/purify.php | 2 +- config/sentry.php | 2 +- config/services.php | 2 +- config/session.php | 5 +- database/factories/FormFactory.php | 4 +- .../2021_05_19_140326_create_forms_table.php | 6 +- ...4_234028_create_form_submissions_table.php | 6 +- ...2133_create_form_zapier_webhooks_table.php | 2 +- ...3_142022_create_users_workspaces_table.php | 14 +- .../2022_05_02_092915_form_views.php | 5 +- .../2022_05_10_144947_form_statistic.php | 9 +- ...133641_add_removed_properties_to_forms.php | 7 +- ...06_044038_add_max_submissions_to_forms.php | 3 +- ...36_remove_access_token_from_workspaces.php | 3 +- ..._110344_add_slack_webhook_url_to_forms.php | 3 +- ...22_09_22_092205_create_templates_table.php | 5 +- ...9_26_084721_add_questions_to_templates.php | 7 +- ...2_10_07_122038_add_visibility_to_forms.php | 3 +- ...4803_add_editable_submissions_to_forms.php | 3 +- .../2023_01_28_142618_add_discord_url.php | 3 +- ...e_max_submissions_reached_text_to_text.php | 3 +- ...table_submissions_button_text_to_forms.php | 3 +- ...change_templates_image_url_to_nullable.php | 3 +- ...53317_create_ai_form_completions_table.php | 3 +- .../2023_03_27_173507_create_jobs_table.php | 3 +- ...56_add_confetti_on_submission_to_forms.php | 3 +- ...023_07_20_073728_add_seo_meta_to_forms.php | 9 +- ...710_add_notification_settings_to_forms.php | 5 +- ...3_09_01_052507_add_fields_to_templates.php | 13 +- ..._21_092812_add_creator_id_to_templates.php | 5 +- ...23_10_10_140600_add_auto_save_to_forms.php | 3 +- ..._of_form_prompt_in_ai_form_completions.php | 3 +- ...023_10_30_133259_create_licenses_table.php | 3 +- ...add_custom_domains_to_workspaces_table.php | 6 +- ...61121_add_custom_domain_to_forms_table.php | 3 +- pint.json | 3 + resources/lang/de-DE/passwords.php | 2 +- resources/lang/de-DE/validation.php | 60 +-- resources/lang/es/auth.php | 2 +- resources/lang/es/pagination.php | 2 +- resources/lang/es/passwords.php | 8 +- resources/lang/es/validation.php | 192 ++++---- resources/lang/nb-NO/auth.php | 1 - resources/lang/nb-NO/passwords.php | 2 +- resources/lang/nb-NO/validation.php | 2 +- resources/lang/nb-NO/verification.php | 20 +- resources/lang/pt-BR/auth.php | 2 +- resources/lang/pt-BR/pagination.php | 2 +- resources/lang/pt-BR/passwords.php | 8 +- resources/lang/pt-BR/validation.php | 234 ++++----- resources/lang/zh-CN/pagination.php | 2 +- resources/lang/zh-CN/validation.php | 2 +- routes/api.php | 96 ++-- tests/Browser/LoginTest.php | 14 +- tests/Browser/Pages/Home.php | 3 +- tests/Browser/Pages/HomePage.php | 1 - tests/Browser/Pages/Login.php | 12 +- tests/Browser/Pages/Onboarding.php | 1 - tests/Browser/Pages/Page.php | 1 - tests/Browser/Pages/Register.php | 3 +- tests/Browser/RegisterTest.php | 6 +- tests/DuskTestCase.php | 14 +- tests/Feature/Forms/AnswerFormTest.php | 27 +- tests/Feature/Forms/CleanDatabaseTest.php | 16 +- tests/Feature/Forms/ConfirmationEmailTest.php | 35 +- .../Forms/CreateDynamicSelectOptionTest.php | 14 +- tests/Feature/Forms/FormCaptchaTest.php | 2 +- tests/Feature/Forms/FormLogicTest.php | 93 ++-- tests/Feature/Forms/FormPasswordTest.php | 19 +- tests/Feature/Forms/FormPropertyLogicTest.php | 229 +++++---- tests/Feature/Forms/FormStatTest.php | 19 +- tests/Feature/Forms/FormTest.php | 19 +- tests/Feature/Forms/FormUpdateTest.php | 8 +- tests/Feature/Forms/FormViewsTest.php | 1 - .../UpdateWorkspaceSelectOptionJobTest.php | 11 +- tests/Feature/LoginTest.php | 11 +- tests/Feature/RegisterTest.php | 22 +- tests/Feature/SettingsTest.php | 41 +- .../Submissions/EditSubmissionTest.php | 22 +- tests/Feature/TemplateTest.php | 6 +- tests/Feature/VerificationTest.php | 3 - tests/Feature/WorkspaceTest.php | 20 +- tests/Helpers/FormSubmissionDataFactory.php | 16 +- tests/TestCase.php | 4 +- tests/TestHelpers.php | 49 +- .../Forms/FormLogicPropertyResolverTest.php | 135 +++--- .../Storage/StorageFileNameParserTest.php | 2 +- tests/Unit/TestHelpersTest.php | 5 +- 226 files changed, 2338 insertions(+), 2144 deletions(-) create mode 100644 pint.json diff --git a/.github/workflows/laravel.yml b/.github/workflows/laravel.yml index 1c43a20..9586bb8 100644 --- a/.github/workflows/laravel.yml +++ b/.github/workflows/laravel.yml @@ -6,6 +6,47 @@ on: pull_request: jobs: + + code_lint: + runs-on: ubuntu-latest + name: Run code linters + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Get Composer cache directory + id: composer-cache + run: | + echo "::set-output name=dir::$(composer config cache-files-dir)" + + - uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.2 + extensions: dom, curl, mbstring, pdo, sqlite, pdo_sqlite + tools: composer:v2 + coverage: none + + - name: Prepare the environment + run: cp .env.example .env + + - name: Install composer dependencies + run: composer install --prefer-dist --no-interaction --no-progress --ignore-platform-reqs --optimize-autoloader + + - name: Directory permissions + run: chmod -R 777 storage bootstrap/cache + + - name: Run PHP lint check + run: ./vendor/bin/pint --test + tests: runs-on: ubuntu-latest @@ -155,7 +196,7 @@ jobs: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} production-deploy: - needs: [ tests, build-nuxt-app ] + needs: [ code_lint, tests, build-nuxt-app ] if: success() && github.ref == 'refs/heads/main' && github.event_name == 'push' runs-on: ubuntu-latest name: Triggers Deployment (Vapor & Amplify) diff --git a/app/Console/Commands/CleanDatabase.php b/app/Console/Commands/CleanDatabase.php index f9f0af8..1f93e52 100644 --- a/app/Console/Commands/CleanDatabase.php +++ b/app/Console/Commands/CleanDatabase.php @@ -3,9 +3,9 @@ namespace App\Console\Commands; use App\Models\Forms\FormStatistic; -use Illuminate\Console\Command; -use App\Models\Forms\FormView; use App\Models\Forms\FormSubmission; +use App\Models\Forms\FormView; +use Illuminate\Console\Command; use Illuminate\Support\Facades\DB; class CleanDatabase extends Command @@ -51,13 +51,13 @@ class CleanDatabase extends Command ->orderBy('date') ->groupBy('form_id', 'date') ->get()->each(function ($row) use (&$finalData) { - $finalData[$row->form_id."-".$row->date] = [ + $finalData[$row->form_id.'-'.$row->date] = [ 'form_id' => $row->form_id, 'date' => $row->date, 'data' => [ 'views' => $row->views, - 'submissions' => 0 - ] + 'submissions' => 0, + ], ]; }); @@ -68,7 +68,7 @@ class CleanDatabase extends Command ->orderBy('date') ->groupBy('form_id', 'date') ->get()->each(function ($row) use (&$finalData) { - $key = $row->form_id."-".$row->date; + $key = $row->form_id.'-'.$row->date; if (isset($finalData[$key])) { $finalData[$key]['data']['submissions'] = $row->submissions; } else { @@ -77,8 +77,8 @@ class CleanDatabase extends Command 'date' => $row->date, 'data' => [ 'views' => 0, - 'submissions' => $row->submissions - ] + 'submissions' => $row->submissions, + ], ]; } diff --git a/app/Console/Commands/GenerateTemplate.php b/app/Console/Commands/GenerateTemplate.php index 716aa09..63accad 100644 --- a/app/Console/Commands/GenerateTemplate.php +++ b/app/Console/Commands/GenerateTemplate.php @@ -24,9 +24,9 @@ class GenerateTemplate extends Command */ protected $description = 'Generates a new form template from a prompt'; - const MAX_RELATED_TEMPLATES = 8; + public const MAX_RELATED_TEMPLATES = 8; - const FORM_STRUCTURE_PROMPT = <<useStreaming() ->setSystemMessage('You are an assistant helping to generate forms.'); $completer->expectsJson()->completeChat([ - ["role" => "user", "content" => Str::of(self::FORM_STRUCTURE_PROMPT)->replace('[REPLACE]', $this->argument('prompt'))->toString()] + ['role' => 'user', 'content' => Str::of(self::FORM_STRUCTURE_PROMPT)->replace('[REPLACE]', $this->argument('prompt'))->toString()], ]); $formData = $completer->getArray(); $completer->doesNotExpectJson(); $formDescriptionPrompt = Str::of(self::FORM_DESCRIPTION_PROMPT)->replace('[REPLACE]', $this->argument('prompt'))->toString(); $formShortDescription = $completer->completeChat([ - ["role" => "user", "content" => Str::of(self::FORM_SHORT_DESCRIPTION_PROMPT)->replace('[REPLACE]', $this->argument('prompt'))->toString()] + ['role' => 'user', 'content' => Str::of(self::FORM_SHORT_DESCRIPTION_PROMPT)->replace('[REPLACE]', $this->argument('prompt'))->toString()], ])->getString(); // If description is between quotes, remove quotes $formShortDescription = Str::of($formShortDescription)->replaceMatches('/^"(.*)"$/', '$1')->toString(); @@ -250,30 +250,29 @@ class GenerateTemplate extends Command // Now get description and QAs $completer->doesNotExpectJson(); $formDescription = $completer->completeChat([ - ["role" => "user", "content" => $formDescriptionPrompt] + ['role' => 'user', 'content' => $formDescriptionPrompt], ])->getHtml(); $completer->expectsJson(); $formCoverKeywords = $completer->completeChat([ - ["role" => "user", "content" => $formDescriptionPrompt], - ["role" => "assistant", "content" => $formDescription], - ["role" => "user", "content" => self::FORM_IMG_KEYWORDS_PROMPT] + ['role' => 'user', 'content' => $formDescriptionPrompt], + ['role' => 'assistant', 'content' => $formDescription], + ['role' => 'user', 'content' => self::FORM_IMG_KEYWORDS_PROMPT], ])->getArray(); $imageUrl = $this->getImageCoverUrl($formCoverKeywords['search_query']); $formQAs = $completer->completeChat([ - ["role" => "user", "content" => $formDescriptionPrompt], - ["role" => "assistant", "content" => $formDescription], - ["role" => "user", "content" => self::FORM_QAS_PROMPT] + ['role' => 'user', 'content' => $formDescriptionPrompt], + ['role' => 'assistant', 'content' => $formDescription], + ['role' => 'user', 'content' => self::FORM_QAS_PROMPT], ])->getArray(); $completer->doesNotExpectJson(); $formTitle = $completer->completeChat([ - ["role" => "user", "content" => $formDescriptionPrompt], - ["role" => "assistant", "content" => $formDescription], - ["role" => "user", "content" => self::FORM_TITLE_PROMPT] + ['role' => 'user', 'content' => $formDescriptionPrompt], + ['role' => 'assistant', 'content' => $formDescription], + ['role' => 'user', 'content' => self::FORM_TITLE_PROMPT], ])->getString(); - $template = $this->createFormTemplate( $formData, $formTitle, @@ -285,7 +284,7 @@ class GenerateTemplate extends Command $types, $relatedTemplates ); - $this->info('/form-templates/' . $template->slug); + $this->info('/form-templates/'.$template->slug); // Set reverse related Templates $this->setReverseRelatedTemplates($template); @@ -298,34 +297,37 @@ class GenerateTemplate extends Command */ private function getImageCoverUrl($searchQuery): ?string { - $url = 'https://api.unsplash.com/search/photos?query=' . urlencode($searchQuery) . '&client_id=' . config('services.unsplash.access_key'); + $url = 'https://api.unsplash.com/search/photos?query='.urlencode($searchQuery).'&client_id='.config('services.unsplash.access_key'); $response = Http::get($url)->json(); $photoIndex = rand(0, max(count($response['results']) - 1, 10)); if (isset($response['results'][$photoIndex]['urls']['regular'])) { return Str::of($response['results'][$photoIndex]['urls']['regular'])->replace('w=1080', 'w=600')->toString(); } + return null; } private function getIndustries(GptCompleter $completer, string $formPrompt): array { $industriesString = Template::getAllIndustries()->pluck('slug')->join(', '); + return $completer->completeChat([ - ["role" => "user", "content" => Str::of(self::FORM_INDUSTRY_PROMPT) + ['role' => 'user', 'content' => Str::of(self::FORM_INDUSTRY_PROMPT) ->replace('[REPLACE]', $formPrompt) ->replace('[INDUSTRIES]', $industriesString) - ->toString()] + ->toString()], ])->getArray()['industries']; } private function getTypes(GptCompleter $completer, string $formPrompt): array { $typesString = Template::getAllTypes()->pluck('slug')->join(', '); + return $completer->completeChat([ - ["role" => "user", "content" => Str::of(self::FORM_TYPES_PROMPT) + ['role' => 'user', 'content' => Str::of(self::FORM_TYPES_PROMPT) ->replace('[REPLACE]', $formPrompt) ->replace('[TYPES]', $typesString) - ->toString()] + ->toString()], ])->getArray()['types']; } @@ -344,21 +346,21 @@ class GenerateTemplate extends Command } }); arsort($templateScore); // Sort by Score + return array_slice(array_keys($templateScore), 0, self::MAX_RELATED_TEMPLATES); } private function createFormTemplate( - array $formData, - string $formTitle, - string $formDescription, - string $formShortDescription, - array $formQAs, + array $formData, + string $formTitle, + string $formDescription, + string $formShortDescription, + array $formQAs, ?string $imageUrl, - array $industry, - array $types, - array $relatedTemplates - ) - { + array $industry, + array $types, + array $relatedTemplates + ) { // Add property uuids, improve form with options foreach ($formData['properties'] as &$property) { $property['id'] = Str::uuid()->toString(); // Column ID @@ -387,13 +389,15 @@ class GenerateTemplate extends Command 'publicly_listed' => true, 'industries' => $industry, 'types' => $types, - 'related_templates' => $relatedTemplates + 'related_templates' => $relatedTemplates, ]); } private function setReverseRelatedTemplates(Template $newTemplate) { - if (!$newTemplate || count($newTemplate->related_templates) === 0) return; + if (! $newTemplate || count($newTemplate->related_templates) === 0) { + return; + } $templates = Template::whereIn('slug', $newTemplate->related_templates)->get(); foreach ($templates as $template) { diff --git a/app/Console/Commands/Tax/GenerateTaxExport.php b/app/Console/Commands/Tax/GenerateTaxExport.php index 02d836c..5049ea2 100644 --- a/app/Console/Commands/Tax/GenerateTaxExport.php +++ b/app/Console/Commands/Tax/GenerateTaxExport.php @@ -27,34 +27,34 @@ class GenerateTaxExport extends Command */ protected $description = 'Compute Stripe VAT per country'; - const EU_TAX_RATES = [ - "AT" => 20, - "BE" => 21, - "BG" => 20, - "HR" => 25, - "CY" => 19, - "CZ" => 21, - "DK" => 25, - "EE" => 20, - "FI" => 24, - "FR" => 20, - "DE" => 19, - "GR" => 24, - "HU" => 27, - "IE" => 23, - "IT" => 22, - "LV" => 21, - "LT" => 21, - "LU" => 17, - "MT" => 18, - "NL" => 21, - "PL" => 23, - "PT" => 23, - "RO" => 19, - "SK" => 20, - "SI" => 22, - "ES" => 21, - "SE" => 25 + public const EU_TAX_RATES = [ + 'AT' => 20, + 'BE' => 21, + 'BG' => 20, + 'HR' => 25, + 'CY' => 19, + 'CZ' => 21, + 'DK' => 25, + 'EE' => 20, + 'FI' => 24, + 'FR' => 20, + 'DE' => 19, + 'GR' => 24, + 'HU' => 27, + 'IE' => 23, + 'IT' => 22, + 'LV' => 21, + 'LT' => 21, + 'LU' => 17, + 'MT' => 18, + 'NL' => 21, + 'PL' => 23, + 'PT' => 23, + 'RO' => 19, + 'SK' => 20, + 'SI' => 22, + 'ES' => 21, + 'SE' => 25, ]; /** @@ -69,20 +69,22 @@ class GenerateTaxExport extends Command $endDate = $this->option('end-date'); // Validate the date format - if ($startDate && !Carbon::createFromFormat('Y-m-d', $startDate)) { + if ($startDate && ! Carbon::createFromFormat('Y-m-d', $startDate)) { $this->error('Invalid start date format. Use YYYY-MM-DD.'); + return Command::FAILURE; } - if ($endDate && !Carbon::createFromFormat('Y-m-d', $endDate)) { + if ($endDate && ! Carbon::createFromFormat('Y-m-d', $endDate)) { $this->error('Invalid end date format. Use YYYY-MM-DD.'); + return Command::FAILURE; - } else if (!$endDate && $this->option('full-month')) { + } elseif (! $endDate && $this->option('full-month')) { $endDate = Carbon::parse($startDate)->endOfMonth()->endOfDay()->format('Y-m-d'); } - $this->info('Start date: ' . $startDate); - $this->info('End date: ' . $endDate); + $this->info('Start date: '.$startDate); + $this->info('End date: '.$endDate); $processedInvoices = []; @@ -111,6 +113,7 @@ class GenerateTaxExport extends Command // Ignore if payment was refunded if (($invoice->payment_intent->status ?? null) !== 'succeeded') { $paymentNotSuccessfulCount++; + continue; } @@ -132,14 +135,14 @@ class GenerateTaxExport extends Command $aggregatedReport = $this->aggregateReport($processedInvoices); - $filePath = 'opnform-tax-export-per-invoice_' . $startDate . '_' . $endDate . '.xlsx'; + $filePath = 'opnform-tax-export-per-invoice_'.$startDate.'_'.$endDate.'.xlsx'; $this->exportAsXlsx($processedInvoices, $filePath); - $aggregatedReportFilePath = 'opnform-tax-export-aggregated_' . $startDate . '_' . $endDate . '.xlsx'; + $aggregatedReportFilePath = 'opnform-tax-export-aggregated_'.$startDate.'_'.$endDate.'.xlsx'; $this->exportAsXlsx($aggregatedReport, $aggregatedReportFilePath); // Display the results - $this->info('Total invoices: ' . $totalInvoice . ' (with ' . $paymentNotSuccessfulCount . ' payment not successful or trial free invoice)'); + $this->info('Total invoices: '.$totalInvoice.' (with '.$paymentNotSuccessfulCount.' payment not successful or trial free invoice)'); return Command::SUCCESS; } @@ -151,7 +154,7 @@ class GenerateTaxExport extends Command foreach ($invoices as $invoice) { $country = $invoice['cust_country']; $customerType = is_null($invoice['cust_vat_id']) && $this->isEuropeanCountry($country) ? 'individual' : 'business'; - if (!isset($aggregatedReport[$country])) { + if (! isset($aggregatedReport[$country])) { $defaultVal = [ 'count' => 0, 'total_usd' => 0, @@ -163,7 +166,7 @@ class GenerateTaxExport extends Command ]; $aggregatedReport[$country] = [ 'individual' => $defaultVal, - 'business' => $defaultVal + 'business' => $defaultVal, ]; } $aggregatedReport[$country][$customerType]['count']++; @@ -181,10 +184,11 @@ class GenerateTaxExport extends Command $finalReport[] = [ 'country' => $country, 'customer_type' => $customerType, - ...$aggData + ...$aggData, ]; } } + return $finalReport; } @@ -226,7 +230,9 @@ class GenerateTaxExport extends Command if ($taxRate = (self::EU_TAX_RATES[$countryCode] ?? null)) { // If VAT ID is provided, then TAX is 0% - if (!$vatId) return $taxRate; + if (! $vatId) { + return $taxRate; + } } return 0; @@ -241,12 +247,11 @@ class GenerateTaxExport extends Command { if (count($data) == 0) { $this->info('Empty data. No file generated.'); + return; } (new ArrayExport($data))->store($filename, 'local', \Maatwebsite\Excel\Excel::XLSX); - $this->line('File generated: ' . storage_path('app/' . $filename)); + $this->line('File generated: '.storage_path('app/'.$filename)); } - - } diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 32dbc01..b6009cd 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -19,7 +19,6 @@ class Kernel extends ConsoleKernel /** * Define the application's command schedule. * - * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) diff --git a/app/Events/Forms/FormSubmitted.php b/app/Events/Forms/FormSubmitted.php index 51e074c..e0e5aa8 100644 --- a/app/Events/Forms/FormSubmitted.php +++ b/app/Events/Forms/FormSubmitted.php @@ -3,19 +3,18 @@ namespace App\Events\Forms; use App\Models\Forms\Form; -use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PresenceChannel; -use Illuminate\Broadcasting\PrivateChannel; -use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; class FormSubmitted { - use Dispatchable, InteractsWithSockets, SerializesModels; + use Dispatchable; + use InteractsWithSockets; + use SerializesModels; public $form; + public $data; /** diff --git a/app/Events/Models/FormCreated.php b/app/Events/Models/FormCreated.php index a697fd7..e99ddb4 100644 --- a/app/Events/Models/FormCreated.php +++ b/app/Events/Models/FormCreated.php @@ -3,17 +3,15 @@ namespace App\Events\Models; use App\Models\Forms\Form; -use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PresenceChannel; -use Illuminate\Broadcasting\PrivateChannel; -use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; class FormCreated { - use Dispatchable, InteractsWithSockets, SerializesModels; + use Dispatchable; + use InteractsWithSockets; + use SerializesModels; /** * Create a new event instance. @@ -21,5 +19,6 @@ class FormCreated * @return void */ public function __construct(public Form $form) - {} + { + } } diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 45a835d..42101cb 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -47,7 +47,7 @@ class Handler extends ExceptionHandler public function report(Throwable $exception) { - if ($this->shouldReport($exception) ) { + if ($this->shouldReport($exception)) { if (app()->bound('sentry') && $this->sentryShouldReport($exception)) { app('sentry')->captureException($exception); Log::debug('Un-handled Exception: '.$exception->getMessage(), [ @@ -64,7 +64,7 @@ class Handler extends ExceptionHandler public function render($request, Throwable $e) { - if ($this->shouldReport($e) && !in_array(\App::environment(),['testing']) && config('logging.channels.slack.enabled')) { + if ($this->shouldReport($e) && ! in_array(\App::environment(), ['testing']) && config('logging.channels.slack.enabled')) { Log::channel('slack')->error($e); } @@ -78,6 +78,7 @@ class Handler extends ExceptionHandler return false; } } + return true; } } diff --git a/app/Exceptions/VerifyEmailException.php b/app/Exceptions/VerifyEmailException.php index f8ebc89..256a3aa 100644 --- a/app/Exceptions/VerifyEmailException.php +++ b/app/Exceptions/VerifyEmailException.php @@ -7,7 +7,7 @@ use Illuminate\Validation\ValidationException; class VerifyEmailException extends ValidationException { /** - * @param \App\User $user + * @param \App\User $user * @return static */ public static function forUser($user) diff --git a/app/Exceptions/Workspaces/WorkspaceAlreadyExisting.php b/app/Exceptions/Workspaces/WorkspaceAlreadyExisting.php index 9330930..ddc217a 100644 --- a/app/Exceptions/Workspaces/WorkspaceAlreadyExisting.php +++ b/app/Exceptions/Workspaces/WorkspaceAlreadyExisting.php @@ -14,7 +14,7 @@ class WorkspaceAlreadyExisting extends Exception public function getErrorMessage() { $owner = $this->workspace->users()->first(); - if (!$owner) { + if (! $owner) { return 'A user already connected that workspace to another NotionForms account. You or the current workspace owner must have a NotionForms Enterprise subscription for you to add this Notion workspace. Please upgrade with an Enterprise subscription, or contact us to get help.'; diff --git a/app/Exports/FormSubmissionExport.php b/app/Exports/FormSubmissionExport.php index 9e60e95..ced1be0 100644 --- a/app/Exports/FormSubmissionExport.php +++ b/app/Exports/FormSubmissionExport.php @@ -7,7 +7,6 @@ use Maatwebsite\Excel\Concerns\WithHeadingRow; class FormSubmissionExport implements FromArray, WithHeadingRow { - protected array $submissionData; public function __construct(array $submissionData) @@ -15,7 +14,7 @@ class FormSubmissionExport implements FromArray, WithHeadingRow $headingRow = []; $contentRow = []; foreach ($submissionData as $i => $row) { - if($i==0){ + if ($i == 0) { $headingRow[] = $this->cleanColumnNames(array_keys($row)); } $contentRow[] = array_values($row); @@ -23,7 +22,7 @@ class FormSubmissionExport implements FromArray, WithHeadingRow $this->submissionData = [ $headingRow, - $contentRow + $contentRow, ]; } diff --git a/app/Exports/Tax/ArrayExport.php b/app/Exports/Tax/ArrayExport.php index 733f5d8..af065b8 100644 --- a/app/Exports/Tax/ArrayExport.php +++ b/app/Exports/Tax/ArrayExport.php @@ -24,4 +24,3 @@ class ArrayExport implements FromArray, WithHeadings return array_keys($this->data[0]); } } - diff --git a/app/Http/Controllers/Admin/ImpersonationController.php b/app/Http/Controllers/Admin/ImpersonationController.php index c2dbf8a..356ba29 100644 --- a/app/Http/Controllers/Admin/ImpersonationController.php +++ b/app/Http/Controllers/Admin/ImpersonationController.php @@ -5,8 +5,6 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use App\Models\Forms\Form; use App\Models\User; -use Illuminate\Http\Request; -use Illuminate\Support\Facades\Auth; class ImpersonationController extends Controller { @@ -15,7 +13,8 @@ class ImpersonationController extends Controller $this->middleware('moderator'); } - public function impersonate($identifier) { + public function impersonate($identifier) + { $user = null; if (is_numeric($identifier)) { $user = User::find($identifier); @@ -29,17 +28,17 @@ class ImpersonationController extends Controller } } - if (!$user) { + if (! $user) { return $this->error([ - 'message'=> 'User not found.' + 'message' => 'User not found.', ]); - } else if ($user->admin) { + } elseif ($user->admin) { return $this->error([ 'message' => 'You cannot impersonate an admin.', ]); } - \Log::warning('Impersonation started',[ + \Log::warning('Impersonation started', [ 'from_id' => auth()->id(), 'from_email' => auth()->user()->email, 'target_id' => $user->id, @@ -52,7 +51,7 @@ class ImpersonationController extends Controller ])->login($user); return $this->success([ - 'token' => $token + 'token' => $token, ]); } } diff --git a/app/Http/Controllers/Auth/AppSumoAuthController.php b/app/Http/Controllers/Auth/AppSumoAuthController.php index 0fd8cbd..3f9df69 100644 --- a/app/Http/Controllers/Auth/AppSumoAuthController.php +++ b/app/Http/Controllers/Auth/AppSumoAuthController.php @@ -17,14 +17,16 @@ class AppSumoAuthController extends Controller public function handleCallback(Request $request) { - if (!$code = $request->code) { + if (! $code = $request->code) { return response()->json(['message' => 'Healthy'], 200); } $accessToken = $this->retrieveAccessToken($code); $license = $this->fetchOrCreateLicense($accessToken); // If user connected, attach license - if (Auth::check()) return $this->attachLicense($license); + if (Auth::check()) { + return $this->attachLicense($license); + } // otherwise start login flow by passing the encrypted license key id if (is_null($license->user_id)) { @@ -37,7 +39,7 @@ class AppSumoAuthController extends Controller private function retrieveAccessToken(string $requestCode): string { return Http::withHeaders([ - 'Content-type' => 'application/json' + 'Content-type' => 'application/json', ])->post('https://appsumo.com/openid/token/', [ 'grant_type' => 'authorization_code', 'code' => $requestCode, @@ -50,13 +52,13 @@ class AppSumoAuthController extends Controller private function fetchOrCreateLicense(string $accessToken): License { // Fetch license from API - $licenseKey = Http::get('https://appsumo.com/openid/license_key/?access_token=' . $accessToken) + $licenseKey = Http::get('https://appsumo.com/openid/license_key/?access_token='.$accessToken) ->throw() ->json('license_key'); // Fetch or create license model - $license = License::where('license_provider','appsumo')->where('license_key',$licenseKey)->first(); - if (!$license) { + $license = License::where('license_provider', 'appsumo')->where('license_key', $licenseKey)->first(); + if (! $license) { $licenseData = Http::withHeaders([ 'X-AppSumo-Licensing-Key' => config('services.appsumo.api_key'), ])->get('https://api.licensing.appsumo.com/v2/licenses/'.$licenseKey)->json(); @@ -73,8 +75,9 @@ class AppSumoAuthController extends Controller return $license; } - private function attachLicense(License $license) { - if (!Auth::check()) { + private function attachLicense(License $license) + { + if (! Auth::check()) { throw new AuthenticationException('User not authenticated'); } @@ -82,6 +85,7 @@ class AppSumoAuthController extends Controller if (is_null($license->user_id)) { $license->user_id = Auth::id(); $license->save(); + return redirect(front_url('/home?appsumo_connect=1')); } @@ -90,8 +94,6 @@ class AppSumoAuthController extends Controller } /** - * @param User $user - * @param string|null $licenseHash * @return string|null * * Returns null if no license found @@ -100,7 +102,7 @@ class AppSumoAuthController extends Controller */ public static function registerWithLicense(User $user, ?string $licenseHash): ?bool { - if (!$licenseHash) { + if (! $licenseHash) { return null; } $licenseId = decrypt($licenseHash); @@ -109,6 +111,7 @@ class AppSumoAuthController extends Controller if ($license && is_null($license->user_id)) { $license->user_id = $user->id; $license->save(); + return true; } diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index 1f3ebb5..9874a5c 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -23,7 +23,6 @@ class ForgotPasswordController extends Controller /** * Get the response for a successful password reset link. * - * @param \Illuminate\Http\Request $request * @param string $response * @return \Illuminate\Http\RedirectResponse */ @@ -35,7 +34,6 @@ class ForgotPasswordController extends Controller /** * Get the response for a failed password reset link. * - * @param \Illuminate\Http\Request $request * @param string $response * @return \Illuminate\Http\RedirectResponse */ diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index e3ef720..2b2913a 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -26,7 +26,6 @@ class LoginController extends Controller /** * Attempt to log the user into the application. * - * @param \Illuminate\Http\Request $request * @return bool */ protected function attemptLogin(Request $request) @@ -50,7 +49,6 @@ class LoginController extends Controller /** * Get the needed authorization credentials from the request. * - * @param \Illuminate\Http\Request $request * @return array */ protected function credentials(Request $request) @@ -64,7 +62,6 @@ class LoginController extends Controller /** * Send the response after the user was authenticated. * - * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\JsonResponse */ protected function sendLoginResponse(Request $request) @@ -84,7 +81,6 @@ class LoginController extends Controller /** * Get the failed login response instance. * - * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\JsonResponse * * @throws \Illuminate\Validation\ValidationException @@ -104,7 +100,6 @@ class LoginController extends Controller /** * Log the user out of the application. * - * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function logout(Request $request) diff --git a/app/Http/Controllers/Auth/OAuthController.php b/app/Http/Controllers/Auth/OAuthController.php index 8b416ee..2c634f5 100644 --- a/app/Http/Controllers/Auth/OAuthController.php +++ b/app/Http/Controllers/Auth/OAuthController.php @@ -28,7 +28,7 @@ class OAuthController extends Controller /** * Redirect the user to the provider authentication page. * - * @param string $provider + * @param string $provider * @return \Illuminate\Http\RedirectResponse */ public function redirect($provider) @@ -41,7 +41,7 @@ class OAuthController extends Controller /** * Obtain the user information from the provider. * - * @param string $driver + * @param string $driver * @return \Illuminate\Http\Response */ public function handleCallback($provider) @@ -61,8 +61,8 @@ class OAuthController extends Controller } /** - * @param string $provider - * @param \Laravel\Socialite\Contracts\User $sUser + * @param string $provider + * @param \Laravel\Socialite\Contracts\User $sUser * @return \App\Models\User */ protected function findOrCreateUser($provider, $user) @@ -81,15 +81,15 @@ class OAuthController extends Controller } if (User::where('email', $user->getEmail())->exists()) { - throw new EmailTakenException; + throw new EmailTakenException(); } return $this->createUser($provider, $user); } /** - * @param string $provider - * @param \Laravel\Socialite\Contracts\User $sUser + * @param string $provider + * @param \Laravel\Socialite\Contracts\User $sUser * @return \App\Models\User */ protected function createUser($provider, $sUser) diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index df7e99a..3b2c5b6 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -4,8 +4,8 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use App\Http\Resources\UserResource; -use App\Models\Workspace; use App\Models\User; +use App\Models\Workspace; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\RegistersUsers; use Illuminate\Http\Request; @@ -31,8 +31,7 @@ class RegisterController extends Controller /** * The user has been registered. * - * @param \Illuminate\Http\Request $request - * @param \App\User $user + * @param \App\User $user * @return \Illuminate\Http\JsonResponse */ protected function registered(Request $request, User $user) @@ -45,13 +44,13 @@ class RegisterController extends Controller (new UserResource($user))->toArray($request), [ 'appsumo_license' => $this->appsumoLicense, - ])); + ] + )); } /** * Get a validator for an incoming registration request. * - * @param array $data * @return \Illuminate\Contracts\Validation\Validator */ protected function validator(array $data) @@ -64,14 +63,13 @@ class RegisterController extends Controller 'agree_terms' => ['required', Rule::in([true])], 'appsumo_license' => ['nullable'], ], [ - 'agree_terms' => 'Please agree with the terms and conditions.' + 'agree_terms' => 'Please agree with the terms and conditions.', ]); } /** * Create a new user instance after a valid registration. * - * @param array $data * @return \App\User */ protected function create(array $data) @@ -85,14 +83,14 @@ class RegisterController extends Controller 'name' => $data['name'], 'email' => strtolower($data['email']), 'password' => bcrypt($data['password']), - 'hear_about_us' => $data['hear_about_us'] + 'hear_about_us' => $data['hear_about_us'], ]); // Add relation with user $user->workspaces()->sync([ $workspace->id => [ - 'role' => 'admin' - ] + 'role' => 'admin', + ], ], false); $this->appsumoLicense = AppSumoAuthController::registerWithLicense($user, $data['appsumo_license'] ?? null); diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index 3aad249..94598cc 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -23,7 +23,6 @@ class ResetPasswordController extends Controller /** * Get the response for a successful password reset. * - * @param \Illuminate\Http\Request $request * @param string $response * @return \Illuminate\Http\RedirectResponse */ @@ -35,7 +34,6 @@ class ResetPasswordController extends Controller /** * Get the response for a failed password reset. * - * @param \Illuminate\Http\Request $request * @param string $response * @return \Illuminate\Http\RedirectResponse */ diff --git a/app/Http/Controllers/Auth/UserController.php b/app/Http/Controllers/Auth/UserController.php index a637ae9..234ec52 100644 --- a/app/Http/Controllers/Auth/UserController.php +++ b/app/Http/Controllers/Auth/UserController.php @@ -11,23 +11,24 @@ class UserController extends Controller { /** * Get authenticated user. - * */ public function current(Request $request) { return new UserResource($request->user()); } - public function deleteAccount() { + public function deleteAccount() + { $this->middleware('auth'); if (Auth::user()->admin) { return $this->error([ - 'message' => 'Cannot delete an admin. Stay with us ๐Ÿ™' + 'message' => 'Cannot delete an admin. Stay with us ๐Ÿ™', ]); } Auth::user()->delete(); + return $this->success([ - 'message' => 'User deleted.' + 'message' => 'User deleted.', ]); } } diff --git a/app/Http/Controllers/Auth/VerificationController.php b/app/Http/Controllers/Auth/VerificationController.php index 1177efa..2164997 100644 --- a/app/Http/Controllers/Auth/VerificationController.php +++ b/app/Http/Controllers/Auth/VerificationController.php @@ -24,8 +24,7 @@ class VerificationController extends Controller /** * Mark the user's email address as verified. * - * @param \Illuminate\Http\Request $request - * @param \App\User $user + * @param \App\User $user * @return \Illuminate\Http\JsonResponse */ public function verify(Request $request, User $user) @@ -54,7 +53,6 @@ class VerificationController extends Controller /** * Resend the email verification notification. * - * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\JsonResponse */ public function resend(Request $request) diff --git a/app/Http/Controllers/CaddyController.php b/app/Http/Controllers/CaddyController.php index b7bd35f..10d1e5c 100644 --- a/app/Http/Controllers/CaddyController.php +++ b/app/Http/Controllers/CaddyController.php @@ -15,29 +15,30 @@ class CaddyController extends Controller ]); // make sure domain is valid $domain = $request->input('domain'); - if (!preg_match(CustomDomainRequest::CUSTOM_DOMAINS_REGEX, $domain)) { + if (! preg_match(CustomDomainRequest::CUSTOM_DOMAINS_REGEX, $domain)) { return $this->error([ 'success' => false, 'message' => 'Invalid domain', ]); } - \Log::info('Caddy request received',[ + \Log::info('Caddy request received', [ 'domain' => $domain, ]); - if ($workspace = Workspace::whereJsonContains('custom_domains',$domain)->first()) { - \Log::info('Caddy request successful',[ + if ($workspace = Workspace::whereJsonContains('custom_domains', $domain)->first()) { + \Log::info('Caddy request successful', [ 'domain' => $domain, 'workspace' => $workspace->id, ]); + return $this->success([ 'success' => true, 'message' => 'OK', ]); } - \Log::info('Caddy request failed',[ + \Log::info('Caddy request failed', [ 'domain' => $domain, 'workspace' => $workspace?->id, ]); diff --git a/app/Http/Controllers/Content/ChangelogController.php b/app/Http/Controllers/Content/ChangelogController.php index f194b74..2820ada 100644 --- a/app/Http/Controllers/Content/ChangelogController.php +++ b/app/Http/Controllers/Content/ChangelogController.php @@ -3,19 +3,19 @@ namespace App\Http\Controllers\Content; use App\Http\Controllers\Controller; -use Illuminate\Http\Request; class ChangelogController extends Controller { - const CANNY_ENDPOINT = 'https://canny.io/api/v1/'; + public const CANNY_ENDPOINT = 'https://canny.io/api/v1/'; public function index() { return \Cache::remember('changelog_entries', now()->addHour(), function () { - $response = \Http:: post(self::CANNY_ENDPOINT.'entries/list',[ + $response = \Http::post(self::CANNY_ENDPOINT.'entries/list', [ 'apiKey' => config('services.canny.api_key'), 'limit' => 3, ]); + return $response->json('entries'); }); } diff --git a/app/Http/Controllers/Content/FileUploadController.php b/app/Http/Controllers/Content/FileUploadController.php index 3481d8c..f0043d3 100644 --- a/app/Http/Controllers/Content/FileUploadController.php +++ b/app/Http/Controllers/Content/FileUploadController.php @@ -12,7 +12,6 @@ class FileUploadController extends Controller /** * Upload file to local temp * - * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\JsonResponse */ public function upload(Request $request) @@ -23,7 +22,7 @@ class FileUploadController extends Controller return response()->json([ 'uuid' => $uuid, - 'key' => $path + 'key' => $path, ], 201); } } diff --git a/app/Http/Controllers/Content/SignedStorageUrlController.php b/app/Http/Controllers/Content/SignedStorageUrlController.php index e1142fa..4505362 100644 --- a/app/Http/Controllers/Content/SignedStorageUrlController.php +++ b/app/Http/Controllers/Content/SignedStorageUrlController.php @@ -2,19 +2,15 @@ namespace App\Http\Controllers\Content; -use App\Models\User; -use Illuminate\Support\Facades\Auth; -use Illuminate\Support\Facades\Gate; +use Illuminate\Http\Request; use Illuminate\Support\Str; use Laravel\Vapor\Http\Controllers\SignedStorageUrlController as Controller; -use Illuminate\Http\Request; class SignedStorageUrlController extends Controller { /** * Create a new signed URL. * - * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\JsonResponse */ public function store(Request $request) diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index cf07b3c..5931c07 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -9,19 +9,21 @@ use Illuminate\Routing\Controller as BaseController; class Controller extends BaseController { - use AuthorizesRequests, DispatchesJobs, ValidatesRequests; + use AuthorizesRequests; + use DispatchesJobs; + use ValidatesRequests; public function success($data = []) { return response()->json(array_merge([ - 'type' => 'success' + 'type' => 'success', ], $data)); } public function error($data = [], $statusCode = 400) { return response()->json(array_merge([ - 'type' => 'error' + 'type' => 'error', ], $data), $statusCode); } } diff --git a/app/Http/Controllers/Forms/AiFormController.php b/app/Http/Controllers/Forms/AiFormController.php index 8b16703..a46e3d7 100644 --- a/app/Http/Controllers/Forms/AiFormController.php +++ b/app/Http/Controllers/Forms/AiFormController.php @@ -5,8 +5,6 @@ namespace App\Http\Controllers\Forms; use App\Http\Controllers\Controller; use App\Http\Requests\AiGenerateFormRequest; use App\Models\Forms\AI\AiFormCompletion; -use App\Service\OpenAi\GptCompleter; -use Illuminate\Support\Str; class AiFormController extends Controller { @@ -18,8 +16,8 @@ class AiFormController extends Controller 'message' => 'We\'re working on your form, please wait ~1 min.', 'ai_form_completion_id' => AiFormCompletion::create([ 'form_prompt' => $request->input('form_prompt'), - 'ip' => $request->ip() - ])->id + 'ip' => $request->ip(), + ])->id, ]); } @@ -30,7 +28,7 @@ class AiFormController extends Controller } return $this->success([ - 'ai_form_completion' => $aiFormCompletion + 'ai_form_completion' => $aiFormCompletion, ]); } } diff --git a/app/Http/Controllers/Forms/FormController.php b/app/Http/Controllers/Forms/FormController.php index 9e0d85c..8b29d6e 100644 --- a/app/Http/Controllers/Forms/FormController.php +++ b/app/Http/Controllers/Forms/FormController.php @@ -17,7 +17,7 @@ use Illuminate\Support\Str; class FormController extends Controller { - const ASSETS_UPLOAD_PATH = 'assets/forms'; + public const ASSETS_UPLOAD_PATH = 'assets/forms'; private FormCleaner $formCleaner; @@ -36,26 +36,28 @@ class FormController extends Controller $workspaceIsPro = $workspace->is_pro; $forms = $workspace->forms() ->orderByDesc('updated_at') - ->paginate(10)->through(function (Form $form) use ($workspace, $workspaceIsPro){ + ->paginate(10)->through(function (Form $form) use ($workspace, $workspaceIsPro) { - // Add attributes for faster loading - $form->extra = (object) [ - 'loadedWorkspace' => $workspace, - 'workspaceIsPro' => $workspaceIsPro, - 'userIsOwner' => true, - 'cleanings' => $this->formCleaner - ->processForm(request(), $form) - ->simulateCleaning($workspace) - ->getPerformedCleanings() - ]; + // Add attributes for faster loading + $form->extra = (object) [ + 'loadedWorkspace' => $workspace, + 'workspaceIsPro' => $workspaceIsPro, + 'userIsOwner' => true, + 'cleanings' => $this->formCleaner + ->processForm(request(), $form) + ->simulateCleaning($workspace) + ->getPerformedCleanings(), + ]; + + return $form; + }); - return $form; - }); return FormResource::collection($forms); } /** * Return all user forms, used for zapier + * * @throws \Illuminate\Auth\Access\AuthorizationException */ public function indexAll() @@ -66,18 +68,20 @@ class FormController extends Controller $this->authorize('viewAny', Form::class); $workspaceIsPro = $workspace->is_pro; - $newForms = $workspace->forms()->get()->map(function (Form $form) use ($workspace, $workspaceIsPro){ + $newForms = $workspace->forms()->get()->map(function (Form $form) use ($workspace, $workspaceIsPro) { // Add attributes for faster loading $form->extra = (object) [ 'loadedWorkspace' => $workspace, 'workspaceIsPro' => $workspaceIsPro, 'userIsOwner' => true, ]; + return $form; }); $forms = $forms->merge($newForms); } + return FormResource::collection($forms); } @@ -94,13 +98,13 @@ class FormController extends Controller ->getData(); $form = Form::create(array_merge($formData, [ - 'creator_id' => $request->user()->id + 'creator_id' => $request->user()->id, ])); 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' => $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' : ''), 'form' => (new FormResource($form))->setCleanings($this->formCleaner->getPerformedCleanings()), - 'users_first_form' => $request->user()->forms()->count() == 1 + 'users_first_form' => $request->user()->forms()->count() == 1, ]); } @@ -116,13 +120,13 @@ class FormController extends Controller // Set Removed Properties $formData['removed_properties'] = array_merge($form->removed_properties, collect($form->properties)->filter(function ($field) use ($formData) { - return (!Str::of($field['type'])->startsWith('nf-') && !in_array($field['id'], collect($formData['properties'])->pluck("id")->toArray())); + return ! Str::of($field['type'])->startsWith('nf-') && ! in_array($field['id'], collect($formData['properties'])->pluck('id')->toArray()); })->toArray()); $form->update($formData); 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' => $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' : ''), 'form' => (new FormResource($form))->setCleanings($this->formCleaner->getPerformedCleanings()), ]); } @@ -133,8 +137,9 @@ class FormController extends Controller $this->authorize('delete', $form); $form->delete(); + return $this->success([ - 'message' => 'Form was deleted.' + 'message' => 'Form was deleted.', ]); } @@ -150,7 +155,7 @@ class FormController extends Controller return $this->success([ 'message' => 'Form successfully duplicated.', - 'new_form' => new FormResource($formCopy) + 'new_form' => new FormResource($formCopy), ]); } @@ -159,7 +164,7 @@ class FormController extends Controller $form = Form::findOrFail($id); $this->authorize('update', $form); - if ( $option == 'slug') { + if ($option == 'slug') { $form->generateSlug(); } elseif ($option == 'uuid') { $form->slug = Str::uuid(); @@ -168,7 +173,7 @@ class FormController extends Controller return $this->success([ 'message' => 'Form url successfully updated. Your new form url now is: '.$form->share_url.'.', - 'form' => new FormResource($form) + 'form' => new FormResource($form), ]); } @@ -182,8 +187,8 @@ class FormController extends Controller $fileNameParser = StorageFileNameParser::parse($request->url); // Make sure we retrieve the file in tmp storage, move it to persistent - $fileName = PublicFormController::TMP_FILE_UPLOAD_PATH.'/'.$fileNameParser->uuid;; - if (!Storage::exists($fileName)) { + $fileName = PublicFormController::TMP_FILE_UPLOAD_PATH.'/'.$fileNameParser->uuid; + if (! Storage::exists($fileName)) { // File not found, we skip return null; } @@ -192,7 +197,7 @@ class FormController extends Controller return $this->success([ 'message' => 'File uploaded.', - 'url' => route("forms.assets.show", [$fileNameParser->getMovedFileName()]) + 'url' => route('forms.assets.show', [$fileNameParser->getMovedFileName()]), ]); } @@ -205,9 +210,9 @@ class FormController extends Controller $this->authorize('view', $form); $path = Str::of(PublicFormController::FILE_UPLOAD_PATH)->replace('?', $form->id).'/'.$fileName; - if (!Storage::exists($path)) { + if (! Storage::exists($path)) { return $this->error([ - 'message' => 'File not found.' + 'message' => 'File not found.', ]); } diff --git a/app/Http/Controllers/Forms/FormStatsController.php b/app/Http/Controllers/Forms/FormStatsController.php index d6ceaad..7788f1a 100644 --- a/app/Http/Controllers/Forms/FormStatsController.php +++ b/app/Http/Controllers/Forms/FormStatsController.php @@ -19,20 +19,21 @@ class FormStatsController extends Controller $this->authorize('view', $form); - $formStats = $form->statistics()->where('date','>',now()->subDays(29)->startOfDay())->get(); - $periodStats = ["views" => [], "submissions" => []]; + $formStats = $form->statistics()->where('date', '>', now()->subDays(29)->startOfDay())->get(); + $periodStats = ['views' => [], 'submissions' => []]; foreach (CarbonPeriod::create(now()->subDays(29), now()) as $dateObj) { $date = $dateObj->format('d-m-Y'); $statisticData = $formStats->where('date', $dateObj->format('Y-m-d'))->first(); - $periodStats["views"][$date] = $statisticData->data["views"] ?? 0; - $periodStats["submissions"][$date] = $statisticData->data["submissions"] ?? 0; + $periodStats['views'][$date] = $statisticData->data['views'] ?? 0; + $periodStats['submissions'][$date] = $statisticData->data['submissions'] ?? 0; - if($dateObj->toDateString() === now()->toDateString()){ - $periodStats["views"][$date] += $form->views()->count(); - $periodStats["submissions"][$date] += $form->submissions()->whereDate('created_at', '>=', now()->startOfDay())->count(); + if ($dateObj->toDateString() === now()->toDateString()) { + $periodStats['views'][$date] += $form->views()->count(); + $periodStats['submissions'][$date] += $form->submissions()->whereDate('created_at', '>=', now()->startOfDay())->count(); } } + return $periodStats; } } diff --git a/app/Http/Controllers/Forms/FormSubmissionController.php b/app/Http/Controllers/Forms/FormSubmissionController.php index 8b44624..18ef9c3 100644 --- a/app/Http/Controllers/Forms/FormSubmissionController.php +++ b/app/Http/Controllers/Forms/FormSubmissionController.php @@ -2,15 +2,14 @@ namespace App\Http\Controllers\Forms; -use App\Http\Controllers\Controller; -use App\Http\Resources\FormSubmissionResource; -use App\Models\Forms\Form; use App\Exports\FormSubmissionExport; +use App\Http\Controllers\Controller; use App\Http\Requests\AnswerFormRequest; +use App\Http\Resources\FormSubmissionResource; use App\Jobs\Form\StoreFormSubmissionJob; +use App\Models\Forms\Form; use App\Models\Forms\FormSubmission; use App\Service\Forms\FormSubmissionFormatter; -use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; use Maatwebsite\Excel\Facades\Excel; @@ -26,7 +25,7 @@ class FormSubmissionController extends Controller public function submissions(string $id) { - $form = Form::findOrFail((int)$id); + $form = Form::findOrFail((int) $id); $this->authorize('view', $form); return FormSubmissionResource::collection($form->submissions()->paginate(100)); @@ -40,15 +39,16 @@ class FormSubmissionController extends Controller $job->setSubmissionId($submissionId)->handle(); $data = new FormSubmissionResource(FormSubmission::findOrFail($submissionId)); + return $this->success([ 'message' => 'Record successfully updated.', - 'data' => $data + 'data' => $data, ]); } public function export(string $id) { - $form = Form::findOrFail((int)$id); + $form = Form::findOrFail((int) $id); $this->authorize('view', $form); $allRows = []; @@ -61,24 +61,25 @@ class FormSubmissionController extends Controller ->useSignedUrlForFiles(); $allRows[] = [ 'id' => Hashids::encode($row['id']), - 'created_at' => date("Y-m-d H:i", strtotime($row['created_at'])), - ...$formatter->getCleanKeyValue() + 'created_at' => date('Y-m-d H:i', strtotime($row['created_at'])), + ...$formatter->getCleanKeyValue(), ]; } $csvExport = (new FormSubmissionExport($allRows)); + return Excel::download( $csvExport, - $form->slug . '-submission-data.csv', + $form->slug.'-submission-data.csv', \Maatwebsite\Excel\Excel::CSV ); } public function submissionFile($id, $fileName) { - $fileName = Str::of(PublicFormController::FILE_UPLOAD_PATH)->replace('?', $id) . '/' - . urldecode($fileName); + $fileName = Str::of(PublicFormController::FILE_UPLOAD_PATH)->replace('?', $id).'/' + .urldecode($fileName); - if (!Storage::exists($fileName)) { + if (! Storage::exists($fileName)) { return $this->error([ 'message' => 'File not found.', ], 404); diff --git a/app/Http/Controllers/Forms/Integration/FormZapierWebhookController.php b/app/Http/Controllers/Forms/Integration/FormZapierWebhookController.php index 442080b..0b8c024 100644 --- a/app/Http/Controllers/Forms/Integration/FormZapierWebhookController.php +++ b/app/Http/Controllers/Forms/Integration/FormZapierWebhookController.php @@ -5,35 +5,38 @@ namespace App\Http\Controllers\Forms\Integration; use App\Http\Controllers\Controller; use App\Http\Requests\Integration\StoreFormZapierWebhookRequest; use App\Models\Integration\FormZapierWebhook; -use Illuminate\Http\Request; -use Spatie\WebhookServer\WebhookCall; class FormZapierWebhookController extends Controller { /** * Controller for Zappier webhook subscriptions. */ - public function __construct() { -// $this->middleware('subscribed'); + public function __construct() + { + // $this->middleware('subscribed'); $this->middleware('auth'); } - public function store(StoreFormZapierWebhookRequest $request) { + public function store(StoreFormZapierWebhookRequest $request) + { $hook = $request->instanciateHook(); $this->authorize('store', $hook); $hook->save(); + return $this->success([ 'message' => 'Webhook created.', - 'hook' => $hook + 'hook' => $hook, ]); } - public function delete($id) { + public function delete($id) + { $hook = FormZapierWebhook::findOrFail($id); $this->authorize('store', $hook); $hook->delete(); + return $this->success([ 'message' => 'Webhook deleted.', ]); diff --git a/app/Http/Controllers/Forms/PublicFormController.php b/app/Http/Controllers/Forms/PublicFormController.php index 8520b60..d93f516 100644 --- a/app/Http/Controllers/Forms/PublicFormController.php +++ b/app/Http/Controllers/Forms/PublicFormController.php @@ -11,15 +11,15 @@ use App\Models\Forms\FormSubmission; use App\Service\Forms\FormCleaner; use App\Service\WorkspaceHelper; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Storage; use Vinkla\Hashids\Facades\Hashids; class PublicFormController extends Controller { + public const FILE_UPLOAD_PATH = 'forms/?/submissions'; - const FILE_UPLOAD_PATH = 'forms/?/submissions'; - const TMP_FILE_UPLOAD_PATH = 'tmp/'; + public const TMP_FILE_UPLOAD_PATH = 'tmp/'; public function show(Request $request, string $slug) { @@ -27,21 +27,22 @@ class PublicFormController extends Controller if ($form->workspace == null) { // Workspace deleted return $this->error([ - 'message' => 'Form not found.' + 'message' => 'Form not found.', ], 404); } $formCleaner = new FormCleaner(); // Disable pro features if needed - $form->fill($formCleaner + $form->fill( + $formCleaner ->processForm($request, $form) ->performCleaning($form->workspace) ->getData() ); // Increase form view counter if not login - if(!Auth::check()){ + if (! Auth::check()) { $form->views()->create(); } @@ -53,25 +54,26 @@ class PublicFormController extends Controller { // Check that form has user field $form = $request->form; - if (!$form->has_user_field) { + if (! $form->has_user_field) { return []; } // Use serializer $workspace = $form->workspace; + return (new WorkspaceHelper($workspace))->getAllUsers(); } public function showAsset($assetFileName) { $path = FormController::ASSETS_UPLOAD_PATH.'/'.$assetFileName; - if (!Storage::exists($path)) { + if (! Storage::exists($path)) { return $this->error([ 'message' => 'File not found.', - 'file_name' => $assetFileName + 'file_name' => $assetFileName, ]); } - + return redirect()->to(Storage::temporaryUrl($path, now()->addMinutes(5))); } @@ -84,18 +86,18 @@ class PublicFormController extends Controller $job = new StoreFormSubmissionJob($form, $request->validated()); $job->handle(); $submissionId = Hashids::encode($job->getSubmissionId()); - }else{ + } else { StoreFormSubmissionJob::dispatch($form, $request->validated()); } return $this->success(array_merge([ 'message' => 'Form submission saved.', - 'submission_id' => $submissionId + 'submission_id' => $submissionId, ], $request->form->is_pro && $request->form->redirect_url ? [ 'redirect' => true, - 'redirect_url' => $request->form->redirect_url + 'redirect_url' => $request->form->redirect_url, ] : [ - 'redirect' => false + 'redirect' => false, ])); } @@ -104,7 +106,7 @@ class PublicFormController extends Controller $submissionId = ($submissionId) ? Hashids::decode($submissionId) : false; $submissionId = isset($submissionId[0]) ? $submissionId[0] : false; $form = Form::whereSlug($slug)->whereVisibility('public')->firstOrFail(); - if ($form->workspace == null || !$form->editable_submissions || !$submissionId) { + if ($form->workspace == null || ! $form->editable_submissions || ! $submissionId) { return $this->error([ 'message' => 'Not allowed.', ]); @@ -120,5 +122,4 @@ class PublicFormController extends Controller return $this->success(['data' => ($submission) ? $submission->data : []]); } - } diff --git a/app/Http/Controllers/Forms/RecordController.php b/app/Http/Controllers/Forms/RecordController.php index 2a20910..8b69bc4 100644 --- a/app/Http/Controllers/Forms/RecordController.php +++ b/app/Http/Controllers/Forms/RecordController.php @@ -17,8 +17,7 @@ class RecordController extends Controller $record->delete(); return $this->success([ - 'message' => 'Record successfully removed.' + 'message' => 'Record successfully removed.', ]); } - } diff --git a/app/Http/Controllers/Settings/PasswordController.php b/app/Http/Controllers/Settings/PasswordController.php index d71cb22..74a7a20 100644 --- a/app/Http/Controllers/Settings/PasswordController.php +++ b/app/Http/Controllers/Settings/PasswordController.php @@ -10,7 +10,6 @@ class PasswordController extends Controller /** * Update the user's password. * - * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function update(Request $request) diff --git a/app/Http/Controllers/Settings/ProfileController.php b/app/Http/Controllers/Settings/ProfileController.php index 2763499..368fd76 100644 --- a/app/Http/Controllers/Settings/ProfileController.php +++ b/app/Http/Controllers/Settings/ProfileController.php @@ -10,7 +10,6 @@ class ProfileController extends Controller /** * Update the user's profile information. * - * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function update(Request $request) diff --git a/app/Http/Controllers/SitemapController.php b/app/Http/Controllers/SitemapController.php index 712073e..80bcd15 100644 --- a/app/Http/Controllers/SitemapController.php +++ b/app/Http/Controllers/SitemapController.php @@ -2,18 +2,15 @@ namespace App\Http\Controllers; -use Illuminate\Http\Request; -use Spatie\Sitemap\Sitemap; -use Spatie\Sitemap\Tags\Url; use App\Models\Template; +use Illuminate\Http\Request; class SitemapController extends Controller { - public function index(Request $request) { return [ - ...$this->getTemplatesUrls() + ...$this->getTemplatesUrls(), ]; } @@ -23,10 +20,11 @@ class SitemapController extends Controller Template::where('publicly_listed', true)->chunk(100, function ($templates) use (&$urls) { foreach ($templates as $template) { $urls[] = [ - 'loc' => '/templates/' . $template->slug + 'loc' => '/templates/'.$template->slug, ]; } }); + return $urls; } } diff --git a/app/Http/Controllers/SubscriptionController.php b/app/Http/Controllers/SubscriptionController.php index 5bfc684..253eff5 100644 --- a/app/Http/Controllers/SubscriptionController.php +++ b/app/Http/Controllers/SubscriptionController.php @@ -9,10 +9,11 @@ use Laravel\Cashier\Subscription; class SubscriptionController extends Controller { - const SUBSCRIPTION_PLANS = ['monthly', 'yearly']; + public const SUBSCRIPTION_PLANS = ['monthly', 'yearly']; - const PRO_SUBSCRIPTION_NAME = 'default'; - const SUBSCRIPTION_NAMES = [ + public const PRO_SUBSCRIPTION_NAME = 'default'; + + public const SUBSCRIPTION_NAMES = [ self::PRO_SUBSCRIPTION_NAME, ]; @@ -30,7 +31,7 @@ class SubscriptionController extends Controller if ($user->subscriptions()->where('stripe_status', 'past_due')->first()) { return $this->error([ 'message' => 'You already have a past due subscription. Please verify your details in the billing page, - and contact us if the issue persists.' + and contact us if the issue persists.', ]); } @@ -51,18 +52,18 @@ class SubscriptionController extends Controller 'customer_update' => [ 'address' => 'auto', 'name' => 'never', - ] + ], ]); return $this->success([ - 'checkout_url' => $checkout->url + 'checkout_url' => $checkout->url, ]); } public function updateStripeDetails(UpdateStripeDetailsRequest $request) { $user = Auth::user(); - if (!$user->hasStripeId()) { + if (! $user->hasStripeId()) { $user->createAsStripeCustomer(); } $user->updateStripeCustomer([ @@ -78,13 +79,14 @@ class SubscriptionController extends Controller public function billingPortal() { $this->middleware('auth'); - if (!Auth::user()->has_customer_id) { + if (! Auth::user()->has_customer_id) { return $this->error([ - "message" => "Please subscribe before accessing your billing portal." + 'message' => 'Please subscribe before accessing your billing portal.', ]); } + return $this->success([ - 'portal_url' => Auth::user()->billingPortalUrl(front_url('/home')) + 'portal_url' => Auth::user()->billingPortalUrl(front_url('/home')), ]); } diff --git a/app/Http/Controllers/TemplateController.php b/app/Http/Controllers/TemplateController.php index 151f0d6..5cad51b 100644 --- a/app/Http/Controllers/TemplateController.php +++ b/app/Http/Controllers/TemplateController.php @@ -2,7 +2,6 @@ namespace App\Http\Controllers; -use App\Http\Controllers\Controller; use App\Http\Requests\Templates\FormTemplateRequest; use App\Http\Resources\FormTemplateResource; use App\Models\Template; @@ -13,20 +12,20 @@ class TemplateController extends Controller { public function index(Request $request) { - $limit = (int)$request->get('limit', 0); - $onlyMy = (bool)$request->get('onlymy', false); + $limit = (int) $request->get('limit', 0); + $onlyMy = (bool) $request->get('onlymy', false); $templates = Template::when(Auth::check(), function ($query) use ($onlyMy) { - if ($onlyMy) { - $query->where('creator_id', Auth::id()); - } else { - $query->where(function ($query) { - $query->where('publicly_listed', true) - ->orWhere('creator_id', Auth::id()); - }); - } - }) - ->when(!Auth::check(), function ($query) { + if ($onlyMy) { + $query->where('creator_id', Auth::id()); + } else { + $query->where(function ($query) { + $query->where('publicly_listed', true) + ->orWhere('creator_id', Auth::id()); + }); + } + }) + ->when(! Auth::check(), function ($query) { $query->where('publicly_listed', true); }) ->when($limit > 0, function ($query) use ($limit) { @@ -49,7 +48,7 @@ class TemplateController extends Controller return $this->success([ 'message' => 'Template was created.', 'template_id' => $template->id, - 'data' => new FormTemplateResource($template) + 'data' => new FormTemplateResource($template), ]); } @@ -63,7 +62,7 @@ class TemplateController extends Controller return $this->success([ 'message' => 'Template was updated.', 'template_id' => $template->id, - 'data' => new FormTemplateResource($template) + 'data' => new FormTemplateResource($template), ]); } diff --git a/app/Http/Controllers/Webhook/AppSumoController.php b/app/Http/Controllers/Webhook/AppSumoController.php index dfd0375..1bc83d5 100644 --- a/app/Http/Controllers/Webhook/AppSumoController.php +++ b/app/Http/Controllers/Webhook/AppSumoController.php @@ -4,8 +4,8 @@ namespace App\Http\Controllers\Webhook; use App\Http\Controllers\Controller; use App\Models\License; -use Illuminate\Support\Facades\Log; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Log; use Illuminate\Validation\UnauthorizedException; class AppSumoController extends Controller @@ -16,6 +16,7 @@ class AppSumoController extends Controller if ($request->test) { Log::info('[APPSUMO] test request received', $request->toArray()); + return $this->success([ 'message' => 'Webhook received.', 'event' => $request->event, @@ -69,11 +70,13 @@ class AppSumoController extends Controller $license->user_id = $licenseData['user_id'] ?? null; $license->save(); - Log::info('[APPSUMO] creating new license', + Log::info( + '[APPSUMO] creating new license', [ 'license_key' => $license->license_key, 'license_id' => $license->id, - ]); + ] + ); return $license; } diff --git a/app/Http/Controllers/Webhook/StripeController.php b/app/Http/Controllers/Webhook/StripeController.php index a33eaa0..7c7a7c5 100644 --- a/app/Http/Controllers/Webhook/StripeController.php +++ b/app/Http/Controllers/Webhook/StripeController.php @@ -5,13 +5,11 @@ namespace App\Http\Controllers\Webhook; use App\Notifications\Subscription\FailedPaymentNotification; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\App; -use Illuminate\Support\Facades\Log; use Laravel\Cashier\Http\Controllers\WebhookController; use Stripe\Subscription as StripeSubscription; class StripeController extends WebhookController { - public function handleCustomerSubscriptionCreated(array $payload) { return parent::handleCustomerSubscriptionCreated($payload); @@ -19,7 +17,7 @@ class StripeController extends WebhookController /** * Override to add a sleep, and to detect plan upgrades - * @param array $payload + * * @return \Symfony\Component\HttpFoundation\Response|void */ protected function handleCustomerSubscriptionUpdated(array $payload) @@ -59,7 +57,7 @@ class StripeController extends WebhookController if (isset($data['trial_end'])) { $trialEnd = Carbon::createFromTimestamp($data['trial_end']); - if (!$subscription->trial_ends_at || $subscription->trial_ends_at->ne($trialEnd)) { + if (! $subscription->trial_ends_at || $subscription->trial_ends_at->ne($trialEnd)) { $subscription->trial_ends_at = $trialEnd; } } @@ -125,7 +123,7 @@ class StripeController extends WebhookController return $plan; } } + return 'default'; } - } diff --git a/app/Http/Controllers/WorkspaceController.php b/app/Http/Controllers/WorkspaceController.php index dd51121..77be7ce 100644 --- a/app/Http/Controllers/WorkspaceController.php +++ b/app/Http/Controllers/WorkspaceController.php @@ -5,8 +5,8 @@ namespace App\Http\Controllers; use App\Http\Requests\Workspace\CustomDomainRequest; use App\Http\Resources\WorkspaceResource; use App\Models\Workspace; -use Illuminate\Http\Request; use App\Service\WorkspaceHelper; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class WorkspaceController extends Controller @@ -19,6 +19,7 @@ class WorkspaceController extends Controller public function index() { $this->authorize('viewAny', Workspace::class); + return WorkspaceResource::collection(Auth::user()->workspaces); } @@ -34,6 +35,7 @@ class WorkspaceController extends Controller { $request->workspace->custom_domains = $request->customDomains; $request->workspace->save(); + return new WorkspaceResource($request->workspace); } @@ -44,9 +46,10 @@ class WorkspaceController extends Controller $id = $workspace->id; $workspace->delete(); + return $this->success([ 'message' => 'Workspace deleted.', - 'workspace_id' => $id + 'workspace_id' => $id, ]); } @@ -55,7 +58,7 @@ class WorkspaceController extends Controller $user = $request->user(); $this->validate($request, [ - 'name' => 'required' + 'name' => 'required', ]); // Create workspace @@ -67,14 +70,14 @@ class WorkspaceController extends Controller // Add relation with user $user->workspaces()->sync([ $workspace->id => [ - 'role' => 'admin' - ] + 'role' => 'admin', + ], ], false); return $this->success([ 'message' => 'Workspace created.', 'workspace_id' => $workspace->id, - 'workspace' => new WorkspaceResource($workspace) + 'workspace' => new WorkspaceResource($workspace), ]); } } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 1f2eb9d..449bab6 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -22,7 +22,7 @@ class Kernel extends HttpKernel * @var array */ protected $middleware = [ -// \App\Http\Middleware\TrustHosts::class, + // \App\Http\Middleware\TrustHosts::class, \App\Http\Middleware\TrustProxies::class, \Illuminate\Http\Middleware\HandleCors::class, \App\Http\Middleware\PreventRequestsDuringMaintenance::class, @@ -32,7 +32,7 @@ class Kernel extends HttpKernel \App\Http\Middleware\SetLocale::class, AuthenticateJWT::class, CustomDomainRestriction::class, - AcceptsJsonMiddleware::class + AcceptsJsonMiddleware::class, ]; /** diff --git a/app/Http/Middleware/AcceptsJsonMiddleware.php b/app/Http/Middleware/AcceptsJsonMiddleware.php index 65efd7e..5b576fd 100644 --- a/app/Http/Middleware/AcceptsJsonMiddleware.php +++ b/app/Http/Middleware/AcceptsJsonMiddleware.php @@ -10,7 +10,6 @@ class AcceptsJsonMiddleware /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request * @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse */ diff --git a/app/Http/Middleware/AuthenticateJWT.php b/app/Http/Middleware/AuthenticateJWT.php index 8cbc86b..c701d9d 100644 --- a/app/Http/Middleware/AuthenticateJWT.php +++ b/app/Http/Middleware/AuthenticateJWT.php @@ -8,7 +8,7 @@ use Tymon\JWTAuth\Exceptions\JWTException; class AuthenticateJWT { - const API_SERVER_SECRET_HEADER_NAME = 'x-api-secret'; + public const API_SERVER_SECRET_HEADER_NAME = 'x-api-secret'; /** * Verifies the JWT token and validates the IP and User Agent @@ -33,18 +33,19 @@ class AuthenticateJWT } $error = null; - if (!\Hash::check($request->ip(), $payload->get('ip'))) { + if (! \Hash::check($request->ip(), $payload->get('ip'))) { $error = 'Origin IP is invalid'; } - if (!\Hash::check($request->userAgent(), $payload->get('ua'))) { + if (! \Hash::check($request->userAgent(), $payload->get('ua'))) { $error = 'Origin User Agent is invalid'; } if ($error) { auth()->invalidate(); + return response()->json([ - 'message' => $error + 'message' => $error, ], 403); } } diff --git a/app/Http/Middleware/CaddyRequestMiddleware.php b/app/Http/Middleware/CaddyRequestMiddleware.php index 43def15..dcc174e 100644 --- a/app/Http/Middleware/CaddyRequestMiddleware.php +++ b/app/Http/Middleware/CaddyRequestMiddleware.php @@ -12,14 +12,14 @@ class CaddyRequestMiddleware */ public function handle(Request $request, Closure $next) { - if (!config('custom-domains.enabled')) { + if (! config('custom-domains.enabled')) { return response()->json([ 'success' => false, 'message' => 'Custom domains not enabled', ], 401); } - if (config('custom-domains.enabled') && !in_array($request->ip(), config('custom-domains.authorized_ips'))) { + if (config('custom-domains.enabled') && ! in_array($request->ip(), config('custom-domains.authorized_ips'))) { return response()->json([ 'success' => false, 'message' => 'Unauthorized IP', @@ -27,7 +27,7 @@ class CaddyRequestMiddleware } $secret = $request->route('secret'); - if (config('custom-domains.caddy_secret') && (!$secret || $secret !== config('custom-domains.caddy_secret'))) { + if (config('custom-domains.caddy_secret') && (! $secret || $secret !== config('custom-domains.caddy_secret'))) { return response()->json([ 'success' => false, 'message' => 'Unauthorized', diff --git a/app/Http/Middleware/CustomDomainRestriction.php b/app/Http/Middleware/CustomDomainRestriction.php index 4aa2ca7..28df1b5 100644 --- a/app/Http/Middleware/CustomDomainRestriction.php +++ b/app/Http/Middleware/CustomDomainRestriction.php @@ -6,24 +6,24 @@ use App\Http\Requests\Workspace\CustomDomainRequest; use App\Models\Forms\Form; use App\Models\Workspace; use Closure; -use Illuminate\Http\Request; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Http\Request; class CustomDomainRestriction { - const CUSTOM_DOMAIN_HEADER = "x-custom-domain"; + public const CUSTOM_DOMAIN_HEADER = 'x-custom-domain'; /** * Handle an incoming request. */ public function handle(Request $request, Closure $next) { - if (!$request->hasHeader(self::CUSTOM_DOMAIN_HEADER) || !config('custom-domains.enabled')) { + if (! $request->hasHeader(self::CUSTOM_DOMAIN_HEADER) || ! config('custom-domains.enabled')) { return $next($request); } $customDomain = $request->header(self::CUSTOM_DOMAIN_HEADER); - if (!preg_match(CustomDomainRequest::CUSTOM_DOMAINS_REGEX, $customDomain)) { + if (! preg_match(CustomDomainRequest::CUSTOM_DOMAINS_REGEX, $customDomain)) { return response()->json([ 'success' => false, 'message' => 'Invalid domain', @@ -38,7 +38,7 @@ class CustomDomainRestriction } // Check if domain is known - if (!$workspaces = Workspace::whereJsonContains('custom_domains',$customDomain)->get()) { + if (! $workspaces = Workspace::whereJsonContains('custom_domains', $customDomain)->get()) { return response()->json([ 'success' => false, 'message' => 'Unknown domain', diff --git a/app/Http/Middleware/Form/ProForm.php b/app/Http/Middleware/Form/ProForm.php index c924173..59fff8b 100644 --- a/app/Http/Middleware/Form/ProForm.php +++ b/app/Http/Middleware/Form/ProForm.php @@ -11,7 +11,6 @@ class ProForm /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request * @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse */ @@ -22,6 +21,7 @@ class ProForm $request->merge([ 'form' => $form, ]); + return $next($request); } } diff --git a/app/Http/Middleware/Form/ProtectedForm.php b/app/Http/Middleware/Form/ProtectedForm.php index 6bbc947..6f10188 100644 --- a/app/Http/Middleware/Form/ProtectedForm.php +++ b/app/Http/Middleware/Form/ProtectedForm.php @@ -9,27 +9,26 @@ use Illuminate\Support\Facades\Auth; class ProtectedForm { - const PASSWORD_HEADER_NAME = 'form-password'; + public const PASSWORD_HEADER_NAME = 'form-password'; /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request * @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse */ public function handle(Request $request, Closure $next) { - if (!$request->route('slug')) { + if (! $request->route('slug')) { return $next($request); } - $form = Form::where('slug',$request->route('slug'))->firstOrFail(); + $form = Form::where('slug', $request->route('slug'))->firstOrFail(); $request->merge([ 'form' => $form, ]); $userIsFormOwner = Auth::check() && Auth::user()->ownsForm($form); - if (!$userIsFormOwner && $this->isProtected($request, $form)) { + if (! $userIsFormOwner && $this->isProtected($request, $form)) { return response([ 'status' => 'Unauthorized', 'message' => 'Form is protected.', @@ -41,11 +40,11 @@ class ProtectedForm public static function isProtected(Request $request, Form $form) { - if (!$form->has_password) { + if (! $form->has_password) { return false; } - return !self::hasCorrectPassword($request, $form); + return ! self::hasCorrectPassword($request, $form); } public static function hasCorrectPassword(Request $request, Form $form) diff --git a/app/Http/Middleware/Form/ResolveFormMiddleware.php b/app/Http/Middleware/Form/ResolveFormMiddleware.php index b2a6875..63d05c1 100644 --- a/app/Http/Middleware/Form/ResolveFormMiddleware.php +++ b/app/Http/Middleware/Form/ResolveFormMiddleware.php @@ -11,16 +11,16 @@ class ResolveFormMiddleware /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request * @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse */ - public function handle(Request $request, Closure $next, string $routeParamName = "id") - { - $form = Form::where($routeParamName,$request->route($routeParamName))->firstOrFail(); + public function handle(Request $request, Closure $next, string $routeParamName = 'id') + { + $form = Form::where($routeParamName, $request->route($routeParamName))->firstOrFail(); $request->merge([ 'form' => $form, ]); + return $next($request); } } diff --git a/app/Http/Middleware/ImpersonationMiddleware.php b/app/Http/Middleware/ImpersonationMiddleware.php index 36538f0..89c3baf 100644 --- a/app/Http/Middleware/ImpersonationMiddleware.php +++ b/app/Http/Middleware/ImpersonationMiddleware.php @@ -9,14 +9,15 @@ use Tymon\JWTAuth\Exceptions\JWTException; class ImpersonationMiddleware { public const ADMIN_LOG_PREFIX = '[admin_action] '; - const LOG_ROUTES = [ + + public const LOG_ROUTES = [ 'open.forms.store', 'open.forms.update', 'open.forms.duplicate', 'open.forms.regenerate-link', ]; - const ALLOWED_ROUTES = [ + public const ALLOWED_ROUTES = [ 'logout', // Forms @@ -59,14 +60,13 @@ class ImpersonationMiddleware /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next + * @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse */ public function handle(Request $request, Closure $next) { try { - if (!auth()->check() || !auth()->payload()->get('impersonating')) { + if (! auth()->check() || ! auth()->payload()->get('impersonating')) { return $next($request); } } catch (JWTException $e) { @@ -75,22 +75,22 @@ class ImpersonationMiddleware // Check that route is allowed $routeName = $request->route()->getName(); - if (!in_array($routeName, self::ALLOWED_ROUTES)) { + if (! in_array($routeName, self::ALLOWED_ROUTES)) { return response([ 'message' => 'Unauthorized when impersonating', 'route' => $routeName, 'impersonator' => auth()->payload()->get('impersonator_id'), 'impersonated_account' => auth()->id(), 'url' => $request->fullUrl(), - 'payload' => $request->all() + 'payload' => $request->all(), ], 403); - } else if (in_array($routeName, self::LOG_ROUTES)) { - \Log::warning(self::ADMIN_LOG_PREFIX . 'Impersonator action', [ + } elseif (in_array($routeName, self::LOG_ROUTES)) { + \Log::warning(self::ADMIN_LOG_PREFIX.'Impersonator action', [ 'route' => $routeName, 'url' => $request->fullUrl(), 'impersonated_account' => auth()->id(), 'impersonator' => auth()->payload()->get('impersonator_id'), - 'payload' => $request->all() + 'payload' => $request->all(), ]); } diff --git a/app/Http/Middleware/IsAdmin.php b/app/Http/Middleware/IsAdmin.php index d4a61cc..1896ed0 100644 --- a/app/Http/Middleware/IsAdmin.php +++ b/app/Http/Middleware/IsAdmin.php @@ -10,13 +10,11 @@ class IsAdmin /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next * @return mixed */ public function handle(Request $request, Closure $next) { - if ($request->user() && !$request->user()->admin) { + if ($request->user() && ! $request->user()->admin) { // This user is not a paying customer... if ($request->expectsJson()) { return response([ @@ -24,6 +22,7 @@ class IsAdmin 'type' => 'error', ], 403); } + return redirect('home'); } diff --git a/app/Http/Middleware/IsModerator.php b/app/Http/Middleware/IsModerator.php index 8c0150b..2c79fc1 100644 --- a/app/Http/Middleware/IsModerator.php +++ b/app/Http/Middleware/IsModerator.php @@ -10,13 +10,11 @@ class IsModerator /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next * @return mixed */ public function handle(Request $request, Closure $next) { - if ($request->user() && !$request->user()->moderator) { + if ($request->user() && ! $request->user()->moderator) { // This user is not a paying customer... if ($request->expectsJson()) { return response([ @@ -24,6 +22,7 @@ class IsModerator 'type' => 'error', ], 403); } + return redirect('home'); } diff --git a/app/Http/Middleware/IsNotSubscribed.php b/app/Http/Middleware/IsNotSubscribed.php index f53ea7c..a432bef 100644 --- a/app/Http/Middleware/IsNotSubscribed.php +++ b/app/Http/Middleware/IsNotSubscribed.php @@ -10,8 +10,6 @@ class IsNotSubscribed /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next * @return mixed */ public function handle(Request $request, Closure $next) @@ -24,6 +22,7 @@ class IsNotSubscribed 'type' => 'error', ], 401); } + return redirect('billing'); } diff --git a/app/Http/Middleware/IsSubscribed.php b/app/Http/Middleware/IsSubscribed.php index c37c27e..d451dae 100644 --- a/app/Http/Middleware/IsSubscribed.php +++ b/app/Http/Middleware/IsSubscribed.php @@ -10,13 +10,11 @@ class IsSubscribed /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next * @return mixed */ public function handle(Request $request, Closure $next) { - if ($request->user() && !$request->user()->subscribed()) { + if ($request->user() && ! $request->user()->subscribed()) { // This user is not a paying customer... if ($request->expectsJson()) { return response([ @@ -24,6 +22,7 @@ class IsSubscribed 'type' => 'error', ], 401); } + return redirect('billing'); } diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index b7a5c81..84ad4c5 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -12,8 +12,6 @@ class RedirectIfAuthenticated /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next * @param string|null ...$guards * @return mixed */ diff --git a/app/Http/Middleware/SetLocale.php b/app/Http/Middleware/SetLocale.php index 83b63fd..de4636e 100644 --- a/app/Http/Middleware/SetLocale.php +++ b/app/Http/Middleware/SetLocale.php @@ -10,7 +10,6 @@ class SetLocale * Handle an incoming request. * * @param \Illuminate\Http\Request $request - * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) @@ -23,7 +22,7 @@ class SetLocale } /** - * @param \Illuminate\Http\Request $request + * @param \Illuminate\Http\Request $request * @return string|null */ protected function parseLocale($request) diff --git a/app/Http/Middleware/TrimStrings.php b/app/Http/Middleware/TrimStrings.php index 69ef70a..c64762e 100644 --- a/app/Http/Middleware/TrimStrings.php +++ b/app/Http/Middleware/TrimStrings.php @@ -18,10 +18,11 @@ class TrimStrings extends Middleware /** * The route name where this shouldn't be applied + * * @var string[] */ protected $exceptUrls = [ - '/\/api\/forms\/(.*)\/answer/' + '/\/api\/forms\/(.*)\/answer/', ]; public function handle($request, \Closure $next) diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index 7d14bf7..d156910 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -14,6 +14,6 @@ class VerifyCsrfToken extends Middleware protected $except = [ 'stripe/webhook', 'vapor/signed-storage-url', - 'upload-file' + 'upload-file', ]; } diff --git a/app/Http/Requests/AiGenerateFormRequest.php b/app/Http/Requests/AiGenerateFormRequest.php index eeac724..78ea123 100644 --- a/app/Http/Requests/AiGenerateFormRequest.php +++ b/app/Http/Requests/AiGenerateFormRequest.php @@ -14,7 +14,7 @@ class AiGenerateFormRequest extends FormRequest public function rules() { return [ - 'form_prompt' => 'required|string|max:1000' + 'form_prompt' => 'required|string|max:1000', ]; } } diff --git a/app/Http/Requests/AnswerFormRequest.php b/app/Http/Requests/AnswerFormRequest.php index 9909eae..8e381f7 100644 --- a/app/Http/Requests/AnswerFormRequest.php +++ b/app/Http/Requests/AnswerFormRequest.php @@ -3,22 +3,22 @@ namespace App\Http\Requests; use App\Models\Forms\Form; - use App\Rules\StorageFile; -use App\Service\Forms\FormLogicPropertyResolver; -use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Support\Str; -use Illuminate\Validation\Rule; -use Illuminate\Http\Request; use App\Rules\ValidHCaptcha; use App\Rules\ValidPhoneInputRule; use App\Rules\ValidUrl; +use App\Service\Forms\FormLogicPropertyResolver; +use Illuminate\Foundation\Http\FormRequest; +use Illuminate\Http\Request; +use Illuminate\Support\Str; +use Illuminate\Validation\Rule; class AnswerFormRequest extends FormRequest { public Form $form; protected array $requestRules = []; + protected int $maxFileSize; public function __construct(Request $request) @@ -34,7 +34,7 @@ class AnswerFormRequest extends FormRequest */ public function authorize() { - return !$this->form->is_closed && !$this->form->max_number_of_submissions_reached && $this->form->visibility === 'public'; + return ! $this->form->is_closed && ! $this->form->max_number_of_submissions_reached && $this->form->visibility === 'public'; } /** @@ -56,23 +56,24 @@ class AnswerFormRequest extends FormRequest $selectionFields = collect($this->form->properties)->filter(function ($pro) { return in_array($pro['type'], ['select', 'multi_select']); }); - foreach ($selectionFields as $field){ - if(isset($data[$field['id']]) && is_array($data[$field['id']])){ + foreach ($selectionFields as $field) { + if (isset($data[$field['id']]) && is_array($data[$field['id']])) { $data[$field['id']] = array_map(function ($val) use ($field) { $tmpop = collect($field[$field['type']]['options'])->first(function ($op) use ($val) { - return ($op['id'] ?? $op['value'] === $val); + return $op['id'] ?? $op['value'] === $val; }); - return isset($tmpop['name']) ? $tmpop['name'] : ""; + + return isset($tmpop['name']) ? $tmpop['name'] : ''; }, $data[$field['id']]); } - }; + } if (FormLogicPropertyResolver::isRequired($property, $data)) { $rules[] = 'required'; if ($property['type'] == 'checkbox') { // Required for checkboxes means true $rules[] = 'accepted'; - } else if ($property['type'] == 'number' && isset($property['is_rating']) && $property['is_rating']) { + } elseif ($property['type'] == 'number' && isset($property['is_rating']) && $property['is_rating']) { // For star rating, needs a minimum of 1 star $rules[] = 'min:1'; } @@ -107,6 +108,7 @@ class AnswerFormRequest extends FormRequest /** * Renames validated fields (because field names are ids) + * * @return array */ public function attributes() @@ -115,6 +117,7 @@ class AnswerFormRequest extends FormRequest foreach ($this->form->properties as $property) { $fields[$property['id']] = $property['name']; } + return $fields; } @@ -127,21 +130,21 @@ class AnswerFormRequest extends FormRequest { $messages = []; foreach ($this->form->properties as $property) { - if($property['type'] == 'date' && isset($property['date_range']) && $property['date_range']){ - $messages[$property['id'].'.0.required_with'] = "From date is required"; - $messages[$property['id'].'.1.required_with'] = "To date is required"; - $messages[$property['id'].'.0.before_or_equal'] = "From date must be before or equal To date"; + if ($property['type'] == 'date' && isset($property['date_range']) && $property['date_range']) { + $messages[$property['id'].'.0.required_with'] = 'From date is required'; + $messages[$property['id'].'.1.required_with'] = 'To date is required'; + $messages[$property['id'].'.0.before_or_equal'] = 'From date must be before or equal To date'; } if ($property['type'] == 'number' && isset($property['is_rating']) && $property['is_rating']) { - $messages[$property['id'] . '.min'] = "A rating must be selected"; + $messages[$property['id'].'.min'] = 'A rating must be selected'; } } + return $messages; } /** * Return validation rules for a given form property - * @param $property */ private function getPropertyRules($property): array { @@ -153,27 +156,32 @@ class AnswerFormRequest extends FormRequest if ($property['is_rating'] ?? false) { return ['numeric']; } + return ['numeric']; case 'select': case 'multi_select': if (($property['allow_creation'] ?? false)) { return ['string']; } + return [Rule::in($this->getSelectPropertyOptions($property))]; case 'checkbox': return ['boolean']; case 'url': if (isset($property['file_upload']) && $property['file_upload']) { $this->requestRules[$property['id'].'.*'] = [new StorageFile($this->maxFileSize, [], $this->form)]; + return ['array']; } - return [new ValidUrl]; + + return [new ValidUrl()]; case 'files': $allowedFileTypes = []; - if(!empty($property['allowed_file_types'])){ - $allowedFileTypes = explode(",", $property['allowed_file_types']); + if (! empty($property['allowed_file_types'])) { + $allowedFileTypes = explode(',', $property['allowed_file_types']); } $this->requestRules[$property['id'].'.*'] = [new StorageFile($this->maxFileSize, $allowedFileTypes, $this->form)]; + return ['array']; case 'email': return ['email:filter']; @@ -182,14 +190,17 @@ class AnswerFormRequest extends FormRequest $this->requestRules[$property['id'].'.*'] = $this->getRulesForDate($property); $this->requestRules[$property['id'].'.0'] = ['required_with:'.$property['id'].'.1', 'before_or_equal:'.$property['id'].'.1']; $this->requestRules[$property['id'].'.1'] = ['required_with:'.$property['id'].'.0']; + return ['array', 'min:2']; } + return $this->getRulesForDate($property); case 'phone_number': if (isset($property['use_simple_text_input']) && $property['use_simple_text_input']) { return ['string']; } - return ['string', 'min:6', new ValidPhoneInputRule]; + + return ['string', 'min:6', new ValidPhoneInputRule()]; default: return []; } @@ -199,18 +210,20 @@ class AnswerFormRequest extends FormRequest { if (isset($property['disable_past_dates']) && $property['disable_past_dates']) { return ['date', 'after_or_equal:today']; - }else if (isset($property['disable_future_dates']) && $property['disable_future_dates']) { + } elseif (isset($property['disable_future_dates']) && $property['disable_future_dates']) { return ['date', 'before_or_equal:today']; } + return ['date']; } private function getSelectPropertyOptions($property): array { $type = $property['type']; - if (!isset($property[$type])) { + if (! isset($property[$type])) { return []; } + return array_column($property[$type]['options'], 'name'); } @@ -223,25 +236,26 @@ class AnswerFormRequest extends FormRequest $receivedValue = $receivedData[$property['id']] ?? null; // Escape all '\' in select options - if(in_array($property['type'], ['select', 'multi_select']) && !is_null($receivedValue)){ + if (in_array($property['type'], ['select', 'multi_select']) && ! is_null($receivedValue)) { if (is_array($receivedValue)) { $mergeData[$property['id']] = collect($receivedValue)->map(function ($value) { $value = Str::of($value); + return $value->replace( - ["\e", "\f", "\n", "\r", "\t", "\v", "\\"], - ["\\e", "\\f", "\\n", "\\r", "\\t", "\\v", "\\\\"] + ["\e", "\f", "\n", "\r", "\t", "\v", '\\'], + ['\\e', '\\f', '\\n', '\\r', '\\t', '\\v', '\\\\'] )->toString(); })->toArray(); } else { $receivedValue = Str::of($receivedValue); $mergeData[$property['id']] = $receivedValue->replace( - ["\e", "\f", "\n", "\r", "\t", "\v", "\\"], - ["\\e", "\\f", "\\n", "\\r", "\\t", "\\v", "\\\\"] + ["\e", "\f", "\n", "\r", "\t", "\v", '\\'], + ['\\e', '\\f', '\\n', '\\r', '\\t', '\\v', '\\\\'] )->toString(); } } - if($property['type'] === 'phone_number' && (!isset($property['use_simple_text_input']) || !$property['use_simple_text_input']) && $receivedValue && in_array($receivedValue, $countryCodeMapper)){ + if ($property['type'] === 'phone_number' && (! isset($property['use_simple_text_input']) || ! $property['use_simple_text_input']) && $receivedValue && in_array($receivedValue, $countryCodeMapper)) { $mergeData[$property['id']] = null; } }); diff --git a/app/Http/Requests/Integration/StoreFormZapierWebhookRequest.php b/app/Http/Requests/Integration/StoreFormZapierWebhookRequest.php index ddfe2d5..4388410 100644 --- a/app/Http/Requests/Integration/StoreFormZapierWebhookRequest.php +++ b/app/Http/Requests/Integration/StoreFormZapierWebhookRequest.php @@ -17,12 +17,14 @@ class StoreFormZapierWebhookRequest extends FormRequest { return [ 'form_slug' => 'required|exists:forms,slug', - 'hook_url' => 'required|string|url' + 'hook_url' => 'required|string|url', ]; } - public function instanciateHook() { + public function instanciateHook() + { $form = Form::whereSlug($this->form_slug)->firstOrFail(); + return new FormZapierWebhook([ 'form_id' => $form->id, 'hook_url' => $this->hook_url, diff --git a/app/Http/Requests/StoreFormRequest.php b/app/Http/Requests/StoreFormRequest.php index 5e07d2d..515e89e 100644 --- a/app/Http/Requests/StoreFormRequest.php +++ b/app/Http/Requests/StoreFormRequest.php @@ -2,9 +2,6 @@ namespace App\Http\Requests; -use App\Models\Forms\Form; -use Illuminate\Validation\Rule; - class StoreFormRequest extends UserFormRequest { /** diff --git a/app/Http/Requests/Templates/FormTemplateRequest.php b/app/Http/Requests/Templates/FormTemplateRequest.php index 048377c..052f92d 100644 --- a/app/Http/Requests/Templates/FormTemplateRequest.php +++ b/app/Http/Requests/Templates/FormTemplateRequest.php @@ -7,7 +7,7 @@ use Illuminate\Foundation\Http\FormRequest; class FormTemplateRequest extends FormRequest { - const IGNORED_KEYS = [ + public const IGNORED_KEYS = [ 'id', 'creator', 'cleanings', @@ -49,9 +49,10 @@ class FormTemplateRequest extends FormRequest public function rules() { $slugRule = ''; - if($this->id){ + if ($this->id) { $slugRule = ','.$this->id; } + return [ 'form' => 'required|array', 'publicly_listed' => 'boolean', @@ -88,7 +89,7 @@ class FormTemplateRequest extends FormRequest 'types' => $this->types ?? [], 'industries' => $this->industries ?? [], 'related_templates' => $this->related_templates ?? [], - 'questions' => $this->questions ?? [] + 'questions' => $this->questions ?? [], ]); } } diff --git a/app/Http/Requests/UpdateFormRequest.php b/app/Http/Requests/UpdateFormRequest.php index b5c2d49..4363d55 100644 --- a/app/Http/Requests/UpdateFormRequest.php +++ b/app/Http/Requests/UpdateFormRequest.php @@ -4,5 +4,4 @@ namespace App\Http\Requests; class UpdateFormRequest extends UserFormRequest { - } diff --git a/app/Http/Requests/UploadAssetRequest.php b/app/Http/Requests/UploadAssetRequest.php index 51413a6..70c4947 100644 --- a/app/Http/Requests/UploadAssetRequest.php +++ b/app/Http/Requests/UploadAssetRequest.php @@ -7,7 +7,7 @@ use Illuminate\Foundation\Http\FormRequest; class UploadAssetRequest extends FormRequest { - const FORM_ASSET_MAX_SIZE = 5000000; + public const FORM_ASSET_MAX_SIZE = 5000000; /** * Get the validation rules that apply to the request. @@ -22,7 +22,7 @@ class UploadAssetRequest extends FormRequest 'jpg', 'bmp', 'gif', - 'svg' + 'svg', ]; if ($this->offsetExists('type') && $this->get('type') === 'files') { $fileTypes = []; diff --git a/app/Http/Requests/UserFormRequest.php b/app/Http/Requests/UserFormRequest.php index bb38ec1..7444b52 100644 --- a/app/Http/Requests/UserFormRequest.php +++ b/app/Http/Requests/UserFormRequest.php @@ -1,20 +1,17 @@ 'required|string|max:60', 'description' => 'nullable|string|max:2000', 'tags' => 'nullable|array', - 'visibility' => ['required',Rule::in(Form::VISIBILITY)], + 'visibility' => ['required', Rule::in(Form::VISIBILITY)], // Notifications 'notifies' => 'boolean', - 'notification_emails' => ['required_if:notifies,1', new OneEmailPerLine ], + 'notification_emails' => ['required_if:notifies,1', new OneEmailPerLine()], 'send_submission_confirmation' => 'boolean', 'notification_sender' => 'string|max:64', 'notification_subject' => 'string|max:200', @@ -47,11 +44,11 @@ abstract class UserFormRequest extends \Illuminate\Foundation\Http\FormRequest 'notification_settings' => 'nullable', // Customization - 'theme' => ['required',Rule::in(Form::THEMES)], - 'width' => ['required',Rule::in(Form::WIDTHS)], + 'theme' => ['required', Rule::in(Form::THEMES)], + 'width' => ['required', Rule::in(Form::WIDTHS)], 'cover_picture' => 'url|nullable', 'logo_picture' => 'url|nullable', - 'dark_mode' => ['required',Rule::in(Form::DARK_MODE_VALUES)], + 'dark_mode' => ['required', Rule::in(Form::DARK_MODE_VALUES)], 'color' => 'required|string', 'hide_title' => 'required|boolean', 'uppercase_labels' => 'required|boolean', @@ -75,7 +72,7 @@ abstract class UserFormRequest extends \Illuminate\Foundation\Http\FormRequest 'editable_submissions' => 'boolean|nullable', 'editable_submissions_button_text' => 'string|min:1|max:50', 'confetti_on_submission' => 'boolean', - 'auto_save'=> 'boolean', + 'auto_save' => 'boolean', // Properties 'properties' => 'required|array', @@ -90,7 +87,7 @@ abstract class UserFormRequest extends \Illuminate\Foundation\Http\FormRequest 'properties.*.required' => 'boolean|nullable', 'properties.*.multiple' => 'boolean|nullable', 'properties.*.timezone' => 'sometimes|nullable', - 'properties.*.width' => ['sometimes', Rule::in(['full','1/2','1/3','2/3','1/3','3/4','1/4'])], + 'properties.*.width' => ['sometimes', Rule::in(['full', '1/2', '1/3', '2/3', '1/3', '3/4', '1/4'])], 'properties.*.align' => ['sometimes', Rule::in(['left', 'center', 'right', 'justify'])], 'properties.*.allowed_file_types' => 'sometimes|nullable', 'properties.*.use_toggle_switch' => 'boolean|nullable', @@ -127,7 +124,7 @@ abstract class UserFormRequest extends \Illuminate\Foundation\Http\FormRequest // Custom SEO 'seo_meta' => 'nullable|array', - 'custom_domain' => 'sometimes|nullable|regex:'. CustomDomainRequest::CUSTOM_DOMAINS_REGEX, + 'custom_domain' => 'sometimes|nullable|regex:'.CustomDomainRequest::CUSTOM_DOMAINS_REGEX, ]; } diff --git a/app/Http/Requests/Workspace/CustomDomainRequest.php b/app/Http/Requests/Workspace/CustomDomainRequest.php index 87c0383..a400412 100644 --- a/app/Http/Requests/Workspace/CustomDomainRequest.php +++ b/app/Http/Requests/Workspace/CustomDomainRequest.php @@ -8,10 +8,12 @@ use Illuminate\Http\Request; class CustomDomainRequest extends FormRequest { - const CUSTOM_DOMAINS_REGEX = '/^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,20}$/'; + public const CUSTOM_DOMAINS_REGEX = '/^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,20}$/'; public Workspace $workspace; + public array $customDomains = []; + public function __construct(Request $request, Workspace $workspace) { $this->workspace = Workspace::findOrFail($request->workspaceId); @@ -28,13 +30,13 @@ class CustomDomainRequest extends FormRequest 'custom_domains' => [ 'present', 'array', - function($attribute, $value, $fail) { + function ($attribute, $value, $fail) { $errors = []; $domains = collect($value)->filter(function ($domain) { - return !empty( trim($domain) ); - })->each(function($domain) use (&$errors) { - if (!preg_match(self::CUSTOM_DOMAINS_REGEX, $domain)) { - $errors[] = 'Invalid domain: ' . $domain; + return ! empty(trim($domain)); + })->each(function ($domain) use (&$errors) { + if (! preg_match(self::CUSTOM_DOMAINS_REGEX, $domain)) { + $errors[] = 'Invalid domain: '.$domain; } }); @@ -44,16 +46,17 @@ class CustomDomainRequest extends FormRequest $limit = $this->workspace->custom_domain_count_limit; if ($limit && $domains->count() > $limit) { - $fail('You can only add ' . $limit . ' domain(s).'); + $fail('You can only add '.$limit.' domain(s).'); } $this->customDomains = $domains->toArray(); - } - ] + }, + ], ]; } - protected function passedValidation(){ + protected function passedValidation() + { $this->replace(['custom_domains' => $this->customDomains]); } } diff --git a/app/Http/Resources/FormResource.php b/app/Http/Resources/FormResource.php index 28e3b00..bec5b2b 100644 --- a/app/Http/Resources/FormResource.php +++ b/app/Http/Resources/FormResource.php @@ -3,10 +3,8 @@ namespace App\Http\Resources; use App\Http\Middleware\Form\ProtectedForm; -use App\Http\Resources\UserResource; use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Support\Facades\Auth; -use Illuminate\Http\Request; class FormResource extends JsonResource { @@ -20,7 +18,7 @@ class FormResource extends JsonResource */ public function toArray($request) { - if(!$this->userIsFormOwner() && ProtectedForm::isProtected($request, $this->resource)){ + if (! $this->userIsFormOwner() && ProtectedForm::isProtected($request, $this->resource)) { return $this->getProtectedForm(); } @@ -69,6 +67,7 @@ class FormResource extends JsonResource public function setCleanings(array $cleanings) { $this->cleanings = $cleanings; + return $this; } @@ -96,15 +95,18 @@ class FormResource extends JsonResource ]; } - private function getWorkspace() { + private function getWorkspace() + { return $this->extra?->loadedWorkspace ?? $this->workspace; } - private function workspaceIsPro() { + private function workspaceIsPro() + { return $this->extra?->workspaceIsPro ?? $this->getWorkspace()->is_pro ?? $this->is_pro; } - private function userIsFormOwner() { + private function userIsFormOwner() + { return $this->extra?->userIsOwner ?? ( Auth::check() && Auth::user()->ownsForm($this->resource) diff --git a/app/Http/Resources/FormSubmissionResource.php b/app/Http/Resources/FormSubmissionResource.php index ad2b932..20e9775 100644 --- a/app/Http/Resources/FormSubmissionResource.php +++ b/app/Http/Resources/FormSubmissionResource.php @@ -6,7 +6,6 @@ use Illuminate\Http\Resources\Json\JsonResource; class FormSubmissionResource extends JsonResource { - /** * Transform the resource into an array. * @@ -28,13 +27,14 @@ class FormSubmissionResource extends JsonResource private function addExtraData() { $this->data = array_merge($this->data, [ - "created_at" => $this->created_at->toDateTimeString(), - 'id' => $this->id + 'created_at' => $this->created_at->toDateTimeString(), + 'id' => $this->id, ]); } /** * Link to the file (generating signed s3 URL) + * * @return void */ private function generateFileLinks() @@ -45,7 +45,7 @@ class FormSubmissionResource extends JsonResource return in_array($field['type'], ['files', 'signature']); }); foreach ($fileFields as $field) { - if (isset($data[$field['id']]) && !empty($data[$field['id']])) { + if (isset($data[$field['id']]) && ! empty($data[$field['id']])) { $data[$field['id']] = collect($data[$field['id']])->filter(function ($file) { return $file !== null && $file; })->map(function ($file) { diff --git a/app/Http/Resources/FormTemplateResource.php b/app/Http/Resources/FormTemplateResource.php index e74778f..188dd3c 100644 --- a/app/Http/Resources/FormTemplateResource.php +++ b/app/Http/Resources/FormTemplateResource.php @@ -15,7 +15,7 @@ class FormTemplateResource extends JsonResource public function toArray($request) { return array_merge(parent::toArray($request), [ - 'is_new' => $this->created_at->isAfter(now()->subDays(7)) + 'is_new' => $this->created_at->isAfter(now()->subDays(7)), ]); } } diff --git a/app/Http/Resources/UserResource.php b/app/Http/Resources/UserResource.php index 411da8a..a126648 100644 --- a/app/Http/Resources/UserResource.php +++ b/app/Http/Resources/UserResource.php @@ -9,7 +9,7 @@ class UserResource extends JsonResource /** * Transform the resource into an array. * - * @param \Illuminate\Http\Request $request + * @param \Illuminate\Http\Request $request * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable */ public function toArray($request) diff --git a/app/Http/Resources/WorkspaceResource.php b/app/Http/Resources/WorkspaceResource.php index 5ba7232..a7c4b0e 100644 --- a/app/Http/Resources/WorkspaceResource.php +++ b/app/Http/Resources/WorkspaceResource.php @@ -3,7 +3,6 @@ namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; -use Illuminate\Support\Facades\Auth; class WorkspaceResource extends JsonResource { @@ -12,7 +11,7 @@ class WorkspaceResource extends JsonResource /** * Transform the resource into an array. * - * @param \Illuminate\Http\Request $request + * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request) diff --git a/app/Jobs/Form/GenerateAiForm.php b/app/Jobs/Form/GenerateAiForm.php index e9a745c..c0560ef 100644 --- a/app/Jobs/Form/GenerateAiForm.php +++ b/app/Jobs/Form/GenerateAiForm.php @@ -14,7 +14,10 @@ use Illuminate\Support\Str; class GenerateAiForm implements ShouldQueue { - use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + use Dispatchable; + use InteractsWithQueue; + use Queueable; + use SerializesModels; /** * Create a new job instance. @@ -34,7 +37,7 @@ class GenerateAiForm implements ShouldQueue public function handle() { $this->completion->update([ - 'status' => AiFormCompletion::STATUS_PROCESSING + 'status' => AiFormCompletion::STATUS_PROCESSING, ]); $completer = (new GptCompleter(config('services.openai.api_key'))) @@ -44,13 +47,13 @@ class GenerateAiForm implements ShouldQueue try { $completer->completeChat([ - ["role" => "user", "content" => Str::of(GenerateTemplate::FORM_STRUCTURE_PROMPT) - ->replace('[REPLACE]', $this->completion->form_prompt)->toString()] + ['role' => 'user', 'content' => Str::of(GenerateTemplate::FORM_STRUCTURE_PROMPT) + ->replace('[REPLACE]', $this->completion->form_prompt)->toString()], ], 3000); $this->completion->update([ 'status' => AiFormCompletion::STATUS_COMPLETED, - 'result' => $this->cleanOutput($completer->getArray()) + 'result' => $this->cleanOutput($completer->getArray()), ]); } catch (\Exception $e) { $this->onError($e); @@ -76,10 +79,11 @@ class GenerateAiForm implements ShouldQueue $this->onError($exception); } - private function onError(\Throwable $e) { + private function onError(\Throwable $e) + { $this->completion->update([ 'status' => AiFormCompletion::STATUS_FAILED, - 'result' => ['error' => $e->getMessage()] + 'result' => ['error' => $e->getMessage()], ]); } } diff --git a/app/Jobs/Form/StoreFormSubmissionJob.php b/app/Jobs/Form/StoreFormSubmissionJob.php index 871ba9a..2a26e3f 100644 --- a/app/Jobs/Form/StoreFormSubmissionJob.php +++ b/app/Jobs/Form/StoreFormSubmissionJob.php @@ -3,15 +3,14 @@ namespace App\Jobs\Form; use App\Events\Forms\FormSubmitted; -use App\Http\Controllers\Forms\PublicFormController; use App\Http\Controllers\Forms\FormController; +use App\Http\Controllers\Forms\PublicFormController; use App\Http\Requests\AnswerFormRequest; use App\Models\Forms\Form; use App\Models\Forms\FormSubmission; use App\Service\Forms\FormLogicPropertyResolver; use App\Service\Storage\StorageFileNameParser; use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Filesystem\Filesystem; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; @@ -22,7 +21,10 @@ use Vinkla\Hashids\Facades\Hashids; class StoreFormSubmissionJob implements ShouldQueue { - use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + use Dispatchable; + use InteractsWithQueue; + use Queueable; + use SerializesModels; public ?string $submissionId = null; @@ -47,7 +49,7 @@ class StoreFormSubmissionJob implements ShouldQueue $this->storeSubmission($formData); - $formData["submission_id"] = $this->submissionId; + $formData['submission_id'] = $this->submissionId; FormSubmitted::dispatch($this->form, $formData); } @@ -59,6 +61,7 @@ class StoreFormSubmissionJob implements ShouldQueue public function setSubmissionId(int $id) { $this->submissionId = $id; + return $this; } @@ -82,12 +85,13 @@ class StoreFormSubmissionJob implements ShouldQueue */ private function submissionToUpdate(): ?FormSubmission { - if($this->submissionId){ + if ($this->submissionId) { return $this->form->submissions()->findOrFail($this->submissionId); } if ($this->form->editable_submissions && isset($this->submissionData['submission_id']) && $this->submissionData['submission_id']) { $submissionId = $this->submissionData['submission_id'] ? Hashids::decode($this->submissionData['submission_id']) : false; $submissionId = $submissionId[0] ?? null; + return $this->form->submissions()->findOrFail($submissionId); } @@ -111,7 +115,7 @@ class StoreFormSubmissionJob implements ShouldQueue // Do required transformation per type (e.g. file uploads) foreach ($data as $answerKey => $answerValue) { $field = $properties->where('id', $answerKey)->first(); - if (!$field) { + if (! $field) { continue; } @@ -128,10 +132,10 @@ class StoreFormSubmissionJob implements ShouldQueue } } else { if ($field['type'] == 'text' && isset($field['generates_uuid']) && $field['generates_uuid']) { - $finalData[$field['id']] = ($this->form->is_pro) ? Str::uuid() : "Please upgrade your OpenForm subscription to use our ID generation features"; + $finalData[$field['id']] = ($this->form->is_pro) ? Str::uuid() : 'Please upgrade your OpenForm subscription to use our ID generation features'; } else { if ($field['type'] == 'text' && isset($field['generates_auto_increment_id']) && $field['generates_auto_increment_id']) { - $finalData[$field['id']] = ($this->form->is_pro) ? (string) ($this->form->submissions_count + 1) : "Please upgrade your OpenForm subscription to use our ID generation features"; + $finalData[$field['id']] = ($this->form->is_pro) ? (string) ($this->form->submissions_count + 1) : 'Please upgrade your OpenForm subscription to use our ID generation features'; } else { $finalData[$field['id']] = $answerValue; } @@ -139,12 +143,12 @@ class StoreFormSubmissionJob implements ShouldQueue } // For Singrature - if($this->form->is_pro && $field['type'] == 'signature') { + if ($this->form->is_pro && $field['type'] == 'signature') { $finalData[$field['id']] = $this->storeSignature($answerValue); } // For Phone - if($field['type'] == 'phone_number' && $answerValue && ctype_alpha(substr($answerValue, 0, 2)) && (!isset($field['use_simple_text_input']) || !$field['use_simple_text_input'])) { + if ($field['type'] == 'phone_number' && $answerValue && ctype_alpha(substr($answerValue, 0, 2)) && (! isset($field['use_simple_text_input']) || ! $field['use_simple_text_input'])) { $finalData[$field['id']] = substr($answerValue, 2); } } @@ -156,6 +160,7 @@ class StoreFormSubmissionJob implements ShouldQueue private function isSkipForUpload($value) { $newPath = Str::of(PublicFormController::FILE_UPLOAD_PATH)->replace('?', $this->form->id); + return Storage::exists($newPath.'/'.$value); } @@ -173,15 +178,16 @@ class StoreFormSubmissionJob implements ShouldQueue return null; } - if(filter_var($value, FILTER_VALIDATE_URL) !== false && str_contains($value, parse_url(config('app.url'))['host'])) { // In case of prefill we have full url so convert to s3 + if (filter_var($value, FILTER_VALIDATE_URL) !== false && str_contains($value, parse_url(config('app.url'))['host'])) { // In case of prefill we have full url so convert to s3 $fileName = basename($value); - $path = FormController::ASSETS_UPLOAD_PATH . '/' . $fileName; + $path = FormController::ASSETS_UPLOAD_PATH.'/'.$fileName; $newPath = Str::of(PublicFormController::FILE_UPLOAD_PATH)->replace('?', $this->form->id); Storage::move($path, $newPath.'/'.$fileName); + return $fileName; } - if($this->isSkipForUpload($value)) { + if ($this->isSkipForUpload($value)) { return $value; } @@ -189,7 +195,7 @@ class StoreFormSubmissionJob implements ShouldQueue // Make sure we retrieve the file in tmp storage, move it to persistent $fileName = PublicFormController::TMP_FILE_UPLOAD_PATH.'/'.$fileNameParser->uuid; - if (!Storage::exists($fileName)) { + if (! Storage::exists($fileName)) { // File not found, we skip return null; } @@ -209,7 +215,7 @@ class StoreFormSubmissionJob implements ShouldQueue private function storeSignature(?string $value) { - if ($value == null || !isset(explode(',', $value)[1])) { + if ($value == null || ! isset(explode(',', $value)[1])) { return null; } @@ -225,7 +231,6 @@ class StoreFormSubmissionJob implements ShouldQueue /** * Adds prefill from hidden fields * - * @param array $formData * @param AnswerFormRequest $request */ private function addHiddenPrefills(array &$formData): void @@ -235,9 +240,9 @@ class StoreFormSubmissionJob implements ShouldQueue return isset($property['hidden']) && isset($property['prefill']) && FormLogicPropertyResolver::isHidden($property, $this->submissionData) - && !is_null($property['prefill']) - && !in_array($property['type'], ['files']) - && !($property['type'] == 'url' && isset($property['file_upload']) && $property['file_upload']); + && ! is_null($property['prefill']) + && ! in_array($property['type'], ['files']) + && ! ($property['type'] == 'url' && isset($property['file_upload']) && $property['file_upload']); })->each(function (array $property) use (&$formData) { if ($property['type'] === 'date' && isset($property['prefill_today']) && $property['prefill_today']) { $formData[$property['id']] = now()->format((isset($property['with_time']) && $property['with_time']) ? 'Y-m-d H:i' : 'Y-m-d'); diff --git a/app/Listeners/FailedWebhookListener.php b/app/Listeners/FailedWebhookListener.php index c5c6f20..97c4a68 100644 --- a/app/Listeners/FailedWebhookListener.php +++ b/app/Listeners/FailedWebhookListener.php @@ -3,8 +3,6 @@ namespace App\Listeners; use App\Notifications\Forms\FailedWebhookNotification; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Queue\InteractsWithQueue; use Spatie\WebhookServer\Events\WebhookCallFailedEvent; class FailedWebhookListener @@ -12,7 +10,7 @@ class FailedWebhookListener /** * Handle the event. * - * @param object $event + * @param object $event * @return void */ public function handle(WebhookCallFailedEvent $event) @@ -24,15 +22,16 @@ class FailedWebhookListener 'webhook_url' => $event->webhookUrl, 'exception' => $event->errorType, 'message' => $event->errorMessage, - 'form_id' => $event->meta['form']->id + 'form_id' => $event->meta['form']->id, ]); + return; } \Log::error('Failed webhook', [ 'webhook_url' => $event->webhookUrl, 'exception' => $event->errorType, - 'message' => $event->errorMessage + 'message' => $event->errorMessage, ]); } } diff --git a/app/Listeners/Forms/FormCreationConfirmation.php b/app/Listeners/Forms/FormCreationConfirmation.php index 1b0bf10..a606662 100644 --- a/app/Listeners/Forms/FormCreationConfirmation.php +++ b/app/Listeners/Forms/FormCreationConfirmation.php @@ -5,12 +5,10 @@ namespace App\Listeners\Forms; use App\Events\Models\FormCreated; use App\Mail\Forms\FormCreationConfirmationMail; use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Queue\InteractsWithQueue; use Illuminate\Support\Facades\Mail; class FormCreationConfirmation implements ShouldQueue { - /** * Handle the event. * diff --git a/app/Listeners/Forms/NotifyFormSubmission.php b/app/Listeners/Forms/NotifyFormSubmission.php index a2da167..9e2ab24 100644 --- a/app/Listeners/Forms/NotifyFormSubmission.php +++ b/app/Listeners/Forms/NotifyFormSubmission.php @@ -2,16 +2,13 @@ namespace App\Listeners\Forms; -use App\Models\Forms\Form; use App\Events\Forms\FormSubmitted; -use Illuminate\Support\Facades\Http; -use Spatie\WebhookServer\WebhookCall; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Support\Facades\Notification; -use App\Service\Forms\FormSubmissionFormatter; -use App\Service\Forms\Webhooks\WebhookHandlerProvider; +use App\Models\Forms\Form; use App\Notifications\Forms\FormSubmissionNotification; +use App\Service\Forms\Webhooks\WebhookHandlerProvider; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Support\Facades\Notification; class NotifyFormSubmission implements ShouldQueue { @@ -46,12 +43,14 @@ class NotifyFormSubmission implements ShouldQueue /** * Sends an email to each email address in the form's notification_emails field - * @param FormSubmitted $event + * * @return void */ private function sendEmailNotifications(FormSubmitted $event) { - if (!$event->form->is_pro || !$event->form->notifies) return; + if (! $event->form->is_pro || ! $event->form->notifies) { + return; + } $subscribers = collect(preg_split("/\r\n|\n|\r/", $event->form->notification_emails))->filter(function ( $email diff --git a/app/Listeners/Forms/SubmissionConfirmation.php b/app/Listeners/Forms/SubmissionConfirmation.php index a641455..ebfcf87 100644 --- a/app/Listeners/Forms/SubmissionConfirmation.php +++ b/app/Listeners/Forms/SubmissionConfirmation.php @@ -12,13 +12,12 @@ use Illuminate\Support\Facades\Mail; * Sends a confirmation to form respondant that form was submitted * * Class SubmissionConfirmation - * @package App\Listeners\Forms */ class SubmissionConfirmation implements ShouldQueue { use InteractsWithQueue; - const RISKY_USERS_LIMIT = 120; + public const RISKY_USERS_LIMIT = 120; /** * Handle the event. @@ -29,17 +28,19 @@ class SubmissionConfirmation implements ShouldQueue public function handle(FormSubmitted $event) { if ( - !$event->form->is_pro || - !$event->form->send_submission_confirmation || + ! $event->form->is_pro || + ! $event->form->send_submission_confirmation || $this->riskLimitReached($event) // To avoid phishing abuse we limit this feature for risky users ) { return; } $email = $this->getRespondentEmail($event); - if (!$email) return; + if (! $email) { + return; + } - \Log::info('Sending submission confirmation',[ + \Log::info('Sending submission confirmation', [ 'recipient' => $email, 'form_id' => $event->form->id, 'form_slug' => $event->form->slug, @@ -50,15 +51,20 @@ class SubmissionConfirmation implements ShouldQueue private function getRespondentEmail(FormSubmitted $event) { // Make sure we only have one email field in the form - $emailFields = collect($event->form->properties)->filter(function($field) { - $hidden = $field['hidden']?? false; - return !$hidden && $field['type'] == 'email'; + $emailFields = collect($event->form->properties)->filter(function ($field) { + $hidden = $field['hidden'] ?? false; + + return ! $hidden && $field['type'] == 'email'; }); - if ($emailFields->count() != 1) return null; + if ($emailFields->count() != 1) { + return null; + } if (isset($event->data[$emailFields->first()['id']])) { $email = $event->data[$emailFields->first()['id']]; - if ($this->validateEmail($email)) return $email; + if ($this->validateEmail($email)) { + return $email; + } } return null; @@ -73,13 +79,16 @@ class SubmissionConfirmation implements ShouldQueue 'form_id' => $event->form->id, 'workspace_id' => $event->form->workspace->id, ]); + return true; } } + return false; } - public static function validateEmail($email): bool { - return (boolean) filter_var($email, FILTER_VALIDATE_EMAIL); + public static function validateEmail($email): bool + { + return (bool) filter_var($email, FILTER_VALIDATE_EMAIL); } } diff --git a/app/Mail/Forms/FormCreationConfirmationMail.php b/app/Mail/Forms/FormCreationConfirmationMail.php index 50104f4..15ade17 100644 --- a/app/Mail/Forms/FormCreationConfirmationMail.php +++ b/app/Mail/Forms/FormCreationConfirmationMail.php @@ -6,12 +6,12 @@ use App\Mail\OpenFormMail; use App\Models\Forms\Form; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class FormCreationConfirmationMail extends OpenFormMail implements ShouldQueue { - use Queueable, SerializesModels; + use Queueable; + use SerializesModels; /** * Create a new message instance. @@ -31,8 +31,8 @@ class FormCreationConfirmationMail extends OpenFormMail implements ShouldQueue public function build() { return $this - ->markdown('mail.form.created',[ - 'form' => $this->form, - ])->subject('Your form was created!'); + ->markdown('mail.form.created', [ + 'form' => $this->form, + ])->subject('Your form was created!'); } } diff --git a/app/Mail/Forms/SubmissionConfirmationMail.php b/app/Mail/Forms/SubmissionConfirmationMail.php index 4e8da4b..93a82ef 100644 --- a/app/Mail/Forms/SubmissionConfirmationMail.php +++ b/app/Mail/Forms/SubmissionConfirmationMail.php @@ -8,13 +8,14 @@ use App\Service\Forms\FormSubmissionFormatter; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Queue\SerializesModels; -use Illuminate\Support\Str; use Illuminate\Support\Arr; +use Illuminate\Support\Str; use Vinkla\Hashids\Facades\Hashids; class SubmissionConfirmationMail extends OpenFormMail implements ShouldQueue { - use Queueable, SerializesModels; + use Queueable; + use SerializesModels; /** * Create a new message instance. @@ -22,7 +23,8 @@ class SubmissionConfirmationMail extends OpenFormMail implements ShouldQueue * @return void */ public function __construct(private FormSubmitted $event) - {} + { + } /** * Build the message. @@ -42,23 +44,25 @@ class SubmissionConfirmationMail extends OpenFormMail implements ShouldQueue ->replyTo($this->getReplyToEmail($form->creator->email)) ->from($this->getFromEmail(), $form->notification_sender) ->subject($form->notification_subject) - ->markdown('mail.form.confirmation-submission-notification',[ + ->markdown('mail.form.confirmation-submission-notification', [ 'fields' => $formatter->getFieldsWithValue(), 'form' => $form, 'noBranding' => $form->no_branding, - 'submission_id' => (isset($this->event->data['submission_id']) && $this->event->data['submission_id']) ? Hashids::encode($this->event->data['submission_id']) : null + 'submission_id' => (isset($this->event->data['submission_id']) && $this->event->data['submission_id']) ? Hashids::encode($this->event->data['submission_id']) : null, ]); } private function getFromEmail() { $originalFromAddress = Str::of(config('mail.from.address'))->explode('@'); - return $originalFromAddress->first(). '+' . time() . '@' . $originalFromAddress->last(); + + return $originalFromAddress->first().'+'.time().'@'.$originalFromAddress->last(); } private function getReplyToEmail($default) { - $replyTo = Arr::get((array)$this->event->form->notification_settings, 'confirmation_reply_to', null); + $replyTo = Arr::get((array) $this->event->form->notification_settings, 'confirmation_reply_to', null); + return $replyTo ?? $default; } } diff --git a/app/Mail/OpenFormMail.php b/app/Mail/OpenFormMail.php index b1d24ad..d7688b1 100644 --- a/app/Mail/OpenFormMail.php +++ b/app/Mail/OpenFormMail.php @@ -3,11 +3,11 @@ namespace App\Mail; use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; abstract class OpenFormMail extends Mailable { - use Queueable, SerializesModels; + use Queueable; + use SerializesModels; } diff --git a/app/Models/Forms/AI/AiFormCompletion.php b/app/Models/Forms/AI/AiFormCompletion.php index df9cab4..5322d6f 100644 --- a/app/Models/Forms/AI/AiFormCompletion.php +++ b/app/Models/Forms/AI/AiFormCompletion.php @@ -10,10 +10,13 @@ class AiFormCompletion extends Model { use HasFactory; - const STATUS_PENDING = 'pending'; - const STATUS_PROCESSING = 'processing'; - const STATUS_COMPLETED = 'completed'; - const STATUS_FAILED = 'failed'; + public const STATUS_PENDING = 'pending'; + + public const STATUS_PROCESSING = 'processing'; + + public const STATUS_COMPLETED = 'completed'; + + public const STATUS_FAILED = 'failed'; protected $table = 'ai_form_completions'; @@ -21,11 +24,11 @@ class AiFormCompletion extends Model 'form_prompt', 'status', 'result', - 'ip' + 'ip', ]; protected $attributes = [ - 'status' => self::STATUS_PENDING + 'status' => self::STATUS_PENDING, ]; protected static function booted() diff --git a/app/Models/Forms/Form.php b/app/Models/Forms/Form.php index 53c4039..31ed118 100644 --- a/app/Models/Forms/Form.php +++ b/app/Models/Forms/Form.php @@ -9,26 +9,31 @@ use App\Models\Traits\CachesAttributes; use App\Models\User; use App\Models\Workspace; use Database\Factories\FormFactory; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; use Spatie\Sluggable\HasSlug; use Spatie\Sluggable\SlugOptions; use Stevebauman\Purify\Facades\Purify; -use Illuminate\Support\Facades\DB; -use Illuminate\Database\Eloquent\Casts\Attribute; class Form extends Model implements CachableAttributes { use CachesAttributes; - const DARK_MODE_VALUES = ['auto', 'light', 'dark']; - const THEMES = ['default', 'simple', 'notion']; - const WIDTHS = ['centered', 'full']; - const VISIBILITY = ['public', 'draft', 'closed']; + use HasFactory; + use HasSlug; + use SoftDeletes; - use HasFactory, HasSlug, SoftDeletes; + public const DARK_MODE_VALUES = ['auto', 'light', 'dark']; + + public const THEMES = ['default', 'simple', 'notion']; + + public const WIDTHS = ['centered', 'full']; + + public const VISIBILITY = ['public', 'draft', 'closed']; protected $fillable = [ 'workspace_id', @@ -94,7 +99,7 @@ class Form extends Model implements CachableAttributes 'password', // Custom SEO - 'seo_meta' + 'seo_meta', ]; protected $casts = [ @@ -104,7 +109,7 @@ class Form extends Model implements CachableAttributes 'tags' => 'array', 'removed_properties' => 'array', 'seo_meta' => 'object', - 'notification_settings' => 'object' + 'notification_settings' => 'object', ]; protected $appends = [ @@ -127,13 +132,13 @@ class Form extends Model implements CachableAttributes 'password', 'tags', 'notification_emails', - 'removed_properties' + 'removed_properties', ]; protected $cachableAttributes = [ 'is_pro', 'views_count', - 'max_file_size' + 'max_file_size', ]; /** @@ -155,14 +160,15 @@ class Form extends Model implements CachableAttributes public function getShareUrlAttribute() { if ($this->custom_domain) { - return 'https://' . $this->custom_domain . '/forms/' . $this->slug; + return 'https://'.$this->custom_domain.'/forms/'.$this->slug; } - return front_url('/forms/' . $this->slug); + + return front_url('/forms/'.$this->slug); } public function getEditUrlAttribute() { - return front_url('/forms/' . $this->slug . '/show'); + return front_url('/forms/'.$this->slug.'/show'); } public function getSubmissionsCountAttribute() @@ -174,9 +180,10 @@ class Form extends Model implements CachableAttributes { return $this->remember('views_count', 15 * 60, function (): int { if (env('DB_CONNECTION') == 'mysql') { - return (int)($this->views()->count() + + return (int) ($this->views()->count() + $this->statistics()->sum(DB::raw("json_extract(data, '$.views')"))); } + return $this->views()->count() + $this->statistics()->sum(DB::raw("cast(data->>'views' as integer)")); }); @@ -204,20 +211,21 @@ class Form extends Model implements CachableAttributes public function getIsClosedAttribute() { - return ($this->closes_at && now()->gt($this->closes_at)); + return $this->closes_at && now()->gt($this->closes_at); } public function getFormPendingSubmissionKeyAttribute() { if ($this->updated_at?->timestamp) { - return "openform-" . $this->id . "-pending-submission-" . substr($this->updated_at?->timestamp, -6); + return 'openform-'.$this->id.'-pending-submission-'.substr($this->updated_at?->timestamp, -6); } + return null; } public function getMaxNumberOfSubmissionsReachedAttribute() { - return ($this->max_submissions_count && $this->max_submissions_count <= $this->submissions_count); + return $this->max_submissions_count && $this->max_submissions_count <= $this->submissions_count; } public function setClosedTextAttribute($value) @@ -232,12 +240,12 @@ class Form extends Model implements CachableAttributes public function getHasPasswordAttribute() { - return !empty($this->password); + return ! empty($this->password); } public function getMaxFileSizeAttribute() { - return $this->remember('max_file_size', 15 * 60, function(): int { + return $this->remember('max_file_size', 15 * 60, function (): int { return $this->workspace->max_file_size; }); } @@ -292,7 +300,7 @@ class Form extends Model implements CachableAttributes return SlugOptions::create() ->doNotGenerateSlugsOnUpdate() ->generateSlugsFrom(function (Form $form) { - return $form->title . ' ' . Str::random(6); + return $form->title.' '.Str::random(6); }) ->saveSlugsTo('slug'); } @@ -302,19 +310,18 @@ class Form extends Model implements CachableAttributes return FormFactory::new(); } - public function getNotifiesWebhookAttribute() { - return !empty($this->webhook_url); + return ! empty($this->webhook_url); } public function getNotifiesDiscordAttribute() { - return !empty($this->discord_webhook_url); + return ! empty($this->discord_webhook_url); } public function getNotifiesSlackAttribute() { - return !empty($this->slack_webhook_url); + return ! empty($this->slack_webhook_url); } } diff --git a/app/Models/Forms/FormStatistic.php b/app/Models/Forms/FormStatistic.php index 50b4388..f4f7c07 100644 --- a/app/Models/Forms/FormStatistic.php +++ b/app/Models/Forms/FormStatistic.php @@ -2,20 +2,19 @@ namespace App\Models\Forms; -use App\Models\Forms\Form; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class FormStatistic extends Model { use HasFactory; - + public $timestamps = false; protected $fillable = [ 'form_id', 'data', - 'date' + 'date', ]; /** @@ -34,5 +33,4 @@ class FormStatistic extends Model { return $this->belongsTo(Form::class); } - } diff --git a/app/Models/Forms/FormSubmission.php b/app/Models/Forms/FormSubmission.php index ea2c400..d67e59a 100644 --- a/app/Models/Forms/FormSubmission.php +++ b/app/Models/Forms/FormSubmission.php @@ -2,7 +2,6 @@ namespace App\Models\Forms; -use App\Models\Forms\Form; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -11,17 +10,18 @@ class FormSubmission extends Model use HasFactory; protected $fillable = [ - 'data' + 'data', ]; protected $casts = [ - 'data' => 'array' + 'data' => 'array', ]; /** * RelationShips */ - public function form() { + public function form() + { return $this->belongsTo(Form::class); } } diff --git a/app/Models/Forms/FormView.php b/app/Models/Forms/FormView.php index 01f95b1..1601d0d 100644 --- a/app/Models/Forms/FormView.php +++ b/app/Models/Forms/FormView.php @@ -2,7 +2,6 @@ namespace App\Models\Forms; -use App\Models\Forms\Form; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -13,7 +12,8 @@ class FormView extends Model /** * RelationShips */ - public function form() { + public function form() + { return $this->belongsTo(Form::class); } } diff --git a/app/Models/Integration/FormZapierWebhook.php b/app/Models/Integration/FormZapierWebhook.php index eb157c4..77c5790 100644 --- a/app/Models/Integration/FormZapierWebhook.php +++ b/app/Models/Integration/FormZapierWebhook.php @@ -7,11 +7,11 @@ use App\Service\Forms\Webhooks\WebhookHandlerProvider; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; -use Spatie\WebhookServer\WebhookCall; class FormZapierWebhook extends Model { - use HasFactory, SoftDeletes; + use HasFactory; + use SoftDeletes; protected $table = 'form_zapier_webhooks'; @@ -28,7 +28,7 @@ class FormZapierWebhook extends Model return $this->belongsTo(Form::class); } - public function triggerHook(array $data) + public function triggerHook(array $data) { WebhookHandlerProvider::getProvider( $this->form, diff --git a/app/Models/License.php b/app/Models/License.php index 0e087c3..3db0d58 100644 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -7,17 +7,17 @@ use Illuminate\Database\Eloquent\Model; class License extends Model { - const STATUS_ACTIVE = 'active'; - const STATUS_INACTIVE = 'inactive'; - use HasFactory; + public const STATUS_ACTIVE = 'active'; + + public const STATUS_INACTIVE = 'inactive'; protected $fillable = [ 'license_key', 'user_id', 'license_provider', 'status', - 'meta' + 'meta', ]; protected $casts = [ diff --git a/app/Models/Template.php b/app/Models/Template.php index 45fa38f..e303741 100644 --- a/app/Models/Template.php +++ b/app/Models/Template.php @@ -11,7 +11,8 @@ use Stevebauman\Purify\Facades\Purify; class Template extends Model { - use HasFactory, HasSlug; + use HasFactory; + use HasSlug; protected $fillable = [ 'creator_id', @@ -25,7 +26,7 @@ class Template extends Model 'publicly_listed', 'industries', 'types', - 'related_templates' + 'related_templates', ]; protected $casts = [ @@ -93,7 +94,8 @@ class Template extends Model array_values( json_decode( file_get_contents(resource_path('data/forms/templates/types.json')), - true) + true + ) ) )->values(); } @@ -104,7 +106,8 @@ class Template extends Model array_values( json_decode( file_get_contents(resource_path('data/forms/templates/industries.json')), - true) + true + ) ) )->values(); } diff --git a/app/Models/Traits/CachableAttributes.php b/app/Models/Traits/CachableAttributes.php index d012505..e9e1174 100644 --- a/app/Models/Traits/CachableAttributes.php +++ b/app/Models/Traits/CachableAttributes.php @@ -9,9 +9,6 @@ interface CachableAttributes /** * Get an item from the cache, or execute the given Closure and store the result. * - * @param string $key - * @param int|null $ttl - * @param Closure $callback * * @return mixed */ @@ -20,8 +17,6 @@ interface CachableAttributes /** * Get an item from the cache, or execute the given Closure and store the result forever. * - * @param string $key - * @param \Closure $callback * * @return mixed */ @@ -29,17 +24,11 @@ interface CachableAttributes /** * Remove an item from the cache. - * - * @param string $key - * - * @return bool */ public function forget(string $key): bool; /** * Remove all items from the cache. - * - * @return bool */ public function flush(): bool; } diff --git a/app/Models/Traits/CachesAttributes.php b/app/Models/Traits/CachesAttributes.php index 0b035d2..d5a6c59 100644 --- a/app/Models/Traits/CachesAttributes.php +++ b/app/Models/Traits/CachesAttributes.php @@ -84,7 +84,7 @@ trait CachesAttributes $this->getTable(), $this->getKey(), $attribute, - $this->updated_at?->timestamp ?? '0' + $this->updated_at?->timestamp ?? '0', ]); } diff --git a/app/Models/User.php b/app/Models/User.php index 317d37a..7f8be62 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -7,14 +7,15 @@ use App\Notifications\ResetPassword; use App\Notifications\VerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; - use Illuminate\Notifications\Notifiable; use Laravel\Cashier\Billable; use Tymon\JWTAuth\Contracts\JWTSubject; class User extends Authenticatable implements JWTSubject { - use Notifiable, HasFactory, Billable; + use Billable; + use HasFactory; + use Notifiable; /** * The attributes that are mass assignable. @@ -25,7 +26,7 @@ class User extends Authenticatable implements JWTSubject 'name', 'email', 'password', - 'hear_about_us' + 'hear_about_us', ]; /** @@ -36,7 +37,7 @@ class User extends Authenticatable implements JWTSubject protected $hidden = [ 'password', 'remember_token', - 'hear_about_us' + 'hear_about_us', ]; /** @@ -59,12 +60,12 @@ class User extends Authenticatable implements JWTSubject public function ownsForm(Form $form) { - return $this->workspaces()->where('workspaces.id',$form->workspace_id)->exists(); + return $this->workspaces()->where('workspaces.id', $form->workspace_id)->exists(); } public function ownsWorkspace(Workspace $workspace) { - return $this->workspaces()->where('workspaces.id',$workspace->id)->exists(); + return $this->workspaces()->where('workspaces.id', $workspace->id)->exists(); } /** @@ -89,12 +90,12 @@ class User extends Authenticatable implements JWTSubject { return $this->subscribed() || in_array($this->email, config('opnform.extra_pro_users_emails')) - || !is_null($this->activeLicense()); + || ! is_null($this->activeLicense()); } public function getHasCustomerIdAttribute() { - return !is_null($this->stripe_id); + return ! is_null($this->stripe_id); } public function getAdminAttribute() @@ -121,7 +122,7 @@ class User extends Authenticatable implements JWTSubject /** * Send the password reset notification. * - * @param string $token + * @param string $token * @return void */ public function sendPasswordResetNotification($token) @@ -136,7 +137,7 @@ class User extends Authenticatable implements JWTSubject */ public function sendEmailVerificationNotification() { - $this->notify(new VerifyEmail); + $this->notify(new VerifyEmail()); } /** @@ -144,7 +145,6 @@ class User extends Authenticatable implements JWTSubject * Relationship * ================================= */ - public function workspaces() { return $this->belongsToMany(Workspace::class); @@ -246,5 +246,4 @@ class User extends Authenticatable implements JWTSubject }); }); } - } diff --git a/app/Models/Workspace.php b/app/Models/Workspace.php index 367602a..f4ecafc 100644 --- a/app/Models/Workspace.php +++ b/app/Models/Workspace.php @@ -10,11 +10,15 @@ use Illuminate\Database\Eloquent\Model; class Workspace extends Model implements CachableAttributes { - use HasFactory, CachesAttributes; + use CachesAttributes; + use HasFactory; + + public const MAX_FILE_SIZE_FREE = 5000000; // 5 MB + + public const MAX_FILE_SIZE_PRO = 50000000; // 50 MB + + public const MAX_DOMAIN_PRO = 1; - const MAX_FILE_SIZE_FREE = 5000000; // 5 MB - const MAX_FILE_SIZE_PRO = 50000000; // 50 MB - const MAX_DOMAIN_PRO = 1; protected $fillable = [ 'name', 'icon', @@ -24,7 +28,7 @@ class Workspace extends Model implements CachableAttributes protected $appends = [ 'is_pro', - 'is_enterprise' + 'is_enterprise', ]; protected $casts = [ @@ -37,16 +41,16 @@ class Workspace extends Model implements CachableAttributes 'is_risky', 'submissions_count', 'max_file_size', - 'custom_domain_count' + 'custom_domain_count', ]; public function getMaxFileSizeAttribute() { - if(is_null(config('cashier.key'))){ + if (is_null(config('cashier.key'))) { return self::MAX_FILE_SIZE_PRO; } - return $this->remember('max_file_size', 15 * 60, function(): int { + return $this->remember('max_file_size', 15 * 60, function (): int { // Return max file size depending on subscription foreach ($this->owners as $owner) { if ($owner->is_subscribed) { @@ -55,6 +59,7 @@ class Workspace extends Model implements CachableAttributes return $license->max_file_size; } } + return self::MAX_FILE_SIZE_PRO; } @@ -64,17 +69,18 @@ class Workspace extends Model implements CachableAttributes public function getCustomDomainCountLimitAttribute() { - if(is_null(config('cashier.key'))){ + if (is_null(config('cashier.key'))) { return null; } - return $this->remember('custom_domain_count', 15 * 60, function(): ?int { + return $this->remember('custom_domain_count', 15 * 60, function (): ?int { foreach ($this->owners as $owner) { if ($owner->is_subscribed) { if ($license = $owner->activeLicense()) { // In case of special License return $license->custom_domain_limit_count; } + return self::MAX_DOMAIN_PRO; } } @@ -85,44 +91,46 @@ class Workspace extends Model implements CachableAttributes public function getIsProAttribute() { - if(is_null(config('cashier.key'))){ + if (is_null(config('cashier.key'))) { return true; // If no paid plan so TRUE for ALL } - return $this->remember('is_pro', 15 * 60, function(): bool { + return $this->remember('is_pro', 15 * 60, function (): bool { // Make sure at least one owner is pro foreach ($this->owners as $owner) { if ($owner->is_subscribed) { return true; } } + return false; }); } public function getIsEnterpriseAttribute() { - if(is_null(config('cashier.key'))){ + if (is_null(config('cashier.key'))) { return true; // If no paid plan so TRUE for ALL } - return $this->remember('is_enterprise', 15 * 60, function(): bool { + return $this->remember('is_enterprise', 15 * 60, function (): bool { // Make sure at least one owner is pro foreach ($this->owners as $owner) { if ($owner->has_enterprise_subscription) { return true; } } + return false; }); } public function getIsRiskyAttribute() { - return $this->remember('is_risky', 15 * 60, function(): bool { + return $this->remember('is_risky', 15 * 60, function (): bool { // A workspace is risky if all of his users are risky foreach ($this->owners as $owner) { - if (!$owner->is_risky) { + if (! $owner->is_risky) { return false; } } @@ -133,7 +141,7 @@ class Workspace extends Model implements CachableAttributes public function getSubmissionsCountAttribute() { - return $this->remember('submissions_count', 15 * 60, function(): int { + return $this->remember('submissions_count', 15 * 60, function (): int { $total = 0; foreach ($this->forms as $form) { $total += $form->submissions_count; @@ -146,7 +154,6 @@ class Workspace extends Model implements CachableAttributes /** * Relationships */ - public function users() { return $this->belongsToMany(User::class); diff --git a/app/Notifications/Forms/FailedWebhookNotification.php b/app/Notifications/Forms/FailedWebhookNotification.php index 230985a..a022f4a 100644 --- a/app/Notifications/Forms/FailedWebhookNotification.php +++ b/app/Notifications/Forms/FailedWebhookNotification.php @@ -6,7 +6,6 @@ use App\Models\Forms\Form; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; -use Illuminate\Support\Str; use Spatie\WebhookServer\Events\WebhookCallFailedEvent; class FailedWebhookNotification extends Notification @@ -14,6 +13,7 @@ class FailedWebhookNotification extends Notification use Queueable; public Form $form; + public string $provider; /** @@ -30,7 +30,7 @@ class FailedWebhookNotification extends Notification /** * Get the notification's delivery channels. * - * @param mixed $notifiable + * @param mixed $notifiable * @return array */ public function via($notifiable) @@ -41,13 +41,13 @@ class FailedWebhookNotification extends Notification /** * Get the mail representation of the notification. * - * @param mixed $notifiable + * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { - return (new MailMessage) - ->subject("Notification issue with your NotionForm: '" . $this->form->title . "'") + return (new MailMessage()) + ->subject("Notification issue with your NotionForm: '".$this->form->title."'") ->markdown('mail.form.webhook-error', [ 'provider' => $this->provider, 'error' => $this->event->errorMessage, diff --git a/app/Notifications/Forms/FormSubmissionNotification.php b/app/Notifications/Forms/FormSubmissionNotification.php index 889f11c..1e2f956 100644 --- a/app/Notifications/Forms/FormSubmissionNotification.php +++ b/app/Notifications/Forms/FormSubmissionNotification.php @@ -8,8 +8,8 @@ use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; -use Illuminate\Support\Str; use Illuminate\Support\Arr; +use Illuminate\Support\Str; class FormSubmissionNotification extends Notification implements ShouldQueue { @@ -52,7 +52,7 @@ class FormSubmissionNotification extends Notification implements ShouldQueue ->outputStringsOnly() ->useSignedUrlForFiles(); - return (new MailMessage) + return (new MailMessage()) ->replyTo($this->getReplyToEmail($notifiable->routes['mail'])) ->from($this->getFromEmail(), config('app.name')) ->subject('New form submission for "'.$this->event->form->title.'"') @@ -65,15 +65,17 @@ class FormSubmissionNotification extends Notification implements ShouldQueue private function getFromEmail() { $originalFromAddress = Str::of(config('mail.from.address'))->explode('@'); - return $originalFromAddress->first(). '+' . time() . '@' . $originalFromAddress->last(); + + return $originalFromAddress->first().'+'.time().'@'.$originalFromAddress->last(); } private function getReplyToEmail($default) { - $replyTo = Arr::get((array)$this->event->form->notification_settings, 'notification_reply_to', null); + $replyTo = Arr::get((array) $this->event->form->notification_settings, 'notification_reply_to', null); if ($replyTo && $this->validateEmail($replyTo)) { return $replyTo; } + return $this->getRespondentEmail() ?? $default; } @@ -83,7 +85,7 @@ class FormSubmissionNotification extends Notification implements ShouldQueue $emailFields = collect($this->event->form->properties)->filter(function ($field) { $hidden = $field['hidden'] ?? false; - return !$hidden && $field['type'] == 'email'; + return ! $hidden && $field['type'] == 'email'; }); if ($emailFields->count() != 1) { return null; @@ -101,7 +103,6 @@ class FormSubmissionNotification extends Notification implements ShouldQueue public static function validateEmail($email): bool { - return (bool)filter_var($email, FILTER_VALIDATE_EMAIL); + return (bool) filter_var($email, FILTER_VALIDATE_EMAIL); } - } diff --git a/app/Notifications/ResetPassword.php b/app/Notifications/ResetPassword.php index 5260531..1f1bc6b 100644 --- a/app/Notifications/ResetPassword.php +++ b/app/Notifications/ResetPassword.php @@ -15,7 +15,7 @@ class ResetPassword extends Notification */ public function toMail($notifiable) { - return (new MailMessage) + return (new MailMessage()) ->line('You are receiving this email because we received a password reset request for your account.') ->action('Reset Password', front_url('password/reset/'.$this->token).'?email='.urlencode($notifiable->email)) ->line('If you did not request a password reset, no further action is required.'); diff --git a/app/Notifications/Subscription/FailedPaymentNotification.php b/app/Notifications/Subscription/FailedPaymentNotification.php index dcb3970..301105b 100644 --- a/app/Notifications/Subscription/FailedPaymentNotification.php +++ b/app/Notifications/Subscription/FailedPaymentNotification.php @@ -30,7 +30,7 @@ class FailedPaymentNotification extends Notification implements ShouldQueue */ public function toMail($notifiable) { - return (new MailMessage) + return (new MailMessage()) ->subject('Your Payment Failed') ->greeting(__('We tried to charge your card for your OpenForm subscription but the payment but did not work.')) ->line(__('Please go to OpenForm, click on your name on the top right corner, and click on "Billing". diff --git a/app/Notifications/VerifyEmail.php b/app/Notifications/VerifyEmail.php index cd03c89..962476e 100644 --- a/app/Notifications/VerifyEmail.php +++ b/app/Notifications/VerifyEmail.php @@ -17,7 +17,9 @@ class VerifyEmail extends Notification protected function verificationUrl($notifiable) { $url = URL::temporarySignedRoute( - 'verification.verify', Carbon::now()->addMinutes(60), ['user' => $notifiable->id] + 'verification.verify', + Carbon::now()->addMinutes(60), + ['user' => $notifiable->id] ); return str_replace('/api', '', $url); diff --git a/app/Policies/FormPolicy.php b/app/Policies/FormPolicy.php index 359d324..e35c9f8 100644 --- a/app/Policies/FormPolicy.php +++ b/app/Policies/FormPolicy.php @@ -13,7 +13,6 @@ class FormPolicy /** * Determine whether the user can view any models. * - * @param \App\Models\User $user * @return mixed */ public function viewAny(User $user) @@ -24,8 +23,6 @@ class FormPolicy /** * Determine whether the user can view the model. * - * @param \App\Models\User $user - * @param \App\Models\Forms\Form $form * @return mixed */ public function view(User $user, Form $form) @@ -36,7 +33,6 @@ class FormPolicy /** * Determine whether the user can create models. * - * @param \App\Models\User $user * @return mixed */ public function create(User $user) @@ -47,8 +43,6 @@ class FormPolicy /** * Determine whether the user can update the model. * - * @param \App\Models\User $user - * @param \App\Models\Forms\Form $form * @return mixed */ public function update(User $user, Form $form) @@ -59,8 +53,6 @@ class FormPolicy /** * Determine whether the user can delete the model. * - * @param \App\Models\User $user - * @param \App\Models\Forms\Form $form * @return mixed */ public function delete(User $user, Form $form) @@ -71,8 +63,6 @@ class FormPolicy /** * Determine whether the user can restore the model. * - * @param \App\Models\User $user - * @param \App\Models\Forms\Form $form * @return mixed */ public function restore(User $user, Form $form) @@ -83,8 +73,6 @@ class FormPolicy /** * Determine whether the user can permanently delete the model. * - * @param \App\Models\User $user - * @param \App\Models\Forms\Form $form * @return mixed */ public function forceDelete(User $user, Form $form) diff --git a/app/Policies/TemplatePolicy.php b/app/Policies/TemplatePolicy.php index 4ad9a94..896f47b 100644 --- a/app/Policies/TemplatePolicy.php +++ b/app/Policies/TemplatePolicy.php @@ -13,7 +13,6 @@ class TemplatePolicy /** * Determine whether the user can create models. * - * @param \App\Models\User $user * @return \Illuminate\Auth\Access\Response|bool */ public function create(User $user) @@ -24,8 +23,6 @@ class TemplatePolicy /** * Determine whether the user can update the model. * - * @param \App\Models\User $user - * @param \App\Models\Template $template * @return mixed */ public function update(User $user, Template $template) @@ -36,8 +33,6 @@ class TemplatePolicy /** * Determine whether the user can delete the model. * - * @param \App\Models\User $user - * @param \App\Models\Template $template * @return mixed */ public function delete(User $user, Template $template) diff --git a/app/Policies/WorkspacePolicy.php b/app/Policies/WorkspacePolicy.php index 23b6f13..57d3913 100644 --- a/app/Policies/WorkspacePolicy.php +++ b/app/Policies/WorkspacePolicy.php @@ -2,8 +2,8 @@ namespace App\Policies; -use App\Models\Workspace; use App\Models\User; +use App\Models\Workspace; use Illuminate\Auth\Access\HandlesAuthorization; class WorkspacePolicy @@ -13,7 +13,6 @@ class WorkspacePolicy /** * Determine whether the user can view any models. * - * @param \App\Models\User $user * @return mixed */ public function viewAny(User $user) @@ -24,8 +23,6 @@ class WorkspacePolicy /** * Determine whether the user can view the model. * - * @param \App\Models\User $user - * @param \App\Models\Workspace $workspace * @return mixed */ public function view(User $user, Workspace $workspace) @@ -36,7 +33,6 @@ class WorkspacePolicy /** * Determine whether the user can create models. * - * @param \App\Models\User $user * @return mixed */ public function create(User $user) @@ -47,8 +43,6 @@ class WorkspacePolicy /** * Determine whether the user can update the model. * - * @param \App\Models\User $user - * @param \App\Models\Workspace $workspace * @return mixed */ public function update(User $user, Workspace $workspace) @@ -59,20 +53,16 @@ class WorkspacePolicy /** * Determine whether the user can delete the model. * - * @param \App\Models\User $user - * @param \App\Models\Workspace $workspace * @return mixed */ public function delete(User $user, Workspace $workspace) { - return !$workspace->owners->where('id',$user->id)->isEmpty() && $user->workspaces()->count() > 1; + return ! $workspace->owners->where('id', $user->id)->isEmpty() && $user->workspaces()->count() > 1; } /** * Determine whether the user can restore the model. * - * @param \App\Models\User $user - * @param \App\Models\Workspace $workspace * @return mixed */ public function restore(User $user, Workspace $workspace) @@ -83,8 +73,6 @@ class WorkspacePolicy /** * Determine whether the user can permanently delete the model. * - * @param \App\Models\User $user - * @param \App\Models\Workspace $workspace * @return mixed */ public function forceDelete(User $user, Workspace $workspace) diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 3fa5d1a..df71bc2 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -5,12 +5,13 @@ namespace App\Providers; use App\Models\Billing\Subscription; use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Support\Facades\Schema; +use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Facades\URL; +use Illuminate\Support\Facades\Validator; use Illuminate\Support\ServiceProvider; use Laravel\Cashier\Cashier; use Laravel\Dusk\DuskServiceProvider; -use Illuminate\Support\Facades\Validator; -use Illuminate\Support\Facades\Storage; -use Illuminate\Support\Facades\URL; + class AppServiceProvider extends ServiceProvider { /** @@ -20,7 +21,7 @@ class AppServiceProvider extends ServiceProvider */ public function boot() { - if(config('filesystems.default') === 'local'){ + if (config('filesystems.default') === 'local') { Storage::disk('local')->buildTemporaryUrlsUsing(function ($path, $expiration, $options) { return URL::temporarySignedRoute( 'local.temp', diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 65c06ac..afd477c 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -6,12 +6,10 @@ use App\Models\Forms\Form; use App\Models\Integration\FormZapierWebhook; use App\Models\Template; use App\Models\Workspace; -use App\Models\User; use App\Policies\FormPolicy; use App\Policies\Integration\FormZapierWebhookPolicy; use App\Policies\TemplatePolicy; use App\Policies\WorkspacePolicy; -use App\Policies\UserPolicy; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; class AuthServiceProvider extends ServiceProvider diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 164266c..38e2e28 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -5,11 +5,9 @@ namespace App\Providers; use App\Events\Forms\FormSubmitted; use App\Events\Models\FormCreated; use App\Listeners\FailedWebhookListener; -use App\Listeners\Auth\RegisteredListener; use App\Listeners\Forms\FormCreationConfirmation; use App\Listeners\Forms\NotifyFormSubmission; use App\Listeners\Forms\SubmissionConfirmation; -use App\Notifications\Forms\FormCreatedNotification; use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; @@ -28,15 +26,15 @@ class EventServiceProvider extends ServiceProvider SendEmailVerificationNotification::class, ], FormCreated::class => [ - FormCreationConfirmation::class + FormCreationConfirmation::class, ], FormSubmitted::class => [ NotifyFormSubmission::class, SubmissionConfirmation::class, ], WebhookCallFailedEvent::class => [ - FailedWebhookListener::class - ] + FailedWebhookListener::class, + ], ]; /** diff --git a/app/Providers/HorizonServiceProvider.php b/app/Providers/HorizonServiceProvider.php index a9f0729..ec98169 100644 --- a/app/Providers/HorizonServiceProvider.php +++ b/app/Providers/HorizonServiceProvider.php @@ -35,7 +35,7 @@ class HorizonServiceProvider extends HorizonApplicationServiceProvider { Gate::define('viewHorizon', function ($user) { return in_array($user->email, [ - 'julien@notionforms.io' + 'julien@notionforms.io', ]); }); } diff --git a/app/Providers/ModelStatsServiceProvider.php b/app/Providers/ModelStatsServiceProvider.php index 8738ac8..a7d821e 100644 --- a/app/Providers/ModelStatsServiceProvider.php +++ b/app/Providers/ModelStatsServiceProvider.php @@ -12,8 +12,6 @@ class ModelStatsServiceProvider extends Provider * Register the LaravelModelStats gate. * * This gate determines who can access ModelStats in non-local environments. - * - * @return void */ protected function gate(): void { diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 989bcff..6fec71b 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -48,7 +48,8 @@ class RouteServiceProvider extends ServiceProvider }); } - protected function registerGlobalRouteParamConstraints() { + protected function registerGlobalRouteParamConstraints() + { Route::pattern('workspaceId', '[0-9]+'); } } diff --git a/app/Rules/FormPropertyLogicRule.php b/app/Rules/FormPropertyLogicRule.php index 6c2db1b..8d46a99 100644 --- a/app/Rules/FormPropertyLogicRule.php +++ b/app/Rules/FormPropertyLogicRule.php @@ -2,23 +2,22 @@ namespace App\Rules; -use Illuminate\Contracts\Validation\Rule; use Illuminate\Contracts\Validation\DataAwareRule; +use Illuminate\Contracts\Validation\Rule; use Illuminate\Support\Str; -class FormPropertyLogicRule implements Rule, DataAwareRule +class FormPropertyLogicRule implements DataAwareRule, Rule { - - const ACTIONS_VALUES = [ + public const ACTIONS_VALUES = [ 'show-block', 'hide-block', 'make-it-optional', 'require-answer', 'enable-block', - 'disable-block' + 'disable-block', ]; - const CONDITION_MAPPING = [ + public const CONDITION_MAPPING = [ 'text' => [ 'comparators' => [ 'equals' => [ @@ -43,35 +42,35 @@ class FormPropertyLogicRule implements Rule, DataAwareRule 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'is_not_empty' => [ 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'content_length_equals' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_does_not_equal' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_greater_than' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_greater_than_or_equal_to' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_less_than' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_less_than_or_equal_to' => [ - 'expected_type' => 'number' - ] - ] + 'expected_type' => 'number', + ], + ], ], 'url' => [ 'comparators' => [ @@ -97,35 +96,35 @@ class FormPropertyLogicRule implements Rule, DataAwareRule 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'is_not_empty' => [ 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'content_length_equals' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_does_not_equal' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_greater_than' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_greater_than_or_equal_to' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_less_than' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_less_than_or_equal_to' => [ - 'expected_type' => 'number' - ] - ] + 'expected_type' => 'number', + ], + ], ], 'email' => [ 'comparators' => [ @@ -151,35 +150,35 @@ class FormPropertyLogicRule implements Rule, DataAwareRule 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'is_not_empty' => [ 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'content_length_equals' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_does_not_equal' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_greater_than' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_greater_than_or_equal_to' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_less_than' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_less_than_or_equal_to' => [ - 'expected_type' => 'number' - ] - ] + 'expected_type' => 'number', + ], + ], ], 'phone_number' => [ 'comparators' => [ @@ -205,35 +204,35 @@ class FormPropertyLogicRule implements Rule, DataAwareRule 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'is_not_empty' => [ 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'content_length_equals' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_does_not_equal' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_greater_than' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_greater_than_or_equal_to' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_less_than' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_less_than_or_equal_to' => [ - 'expected_type' => 'number' - ] - ] + 'expected_type' => 'number', + ], + ], ], 'number' => [ 'comparators' => [ @@ -259,35 +258,35 @@ class FormPropertyLogicRule implements Rule, DataAwareRule 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'is_not_empty' => [ 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'content_length_equals' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_does_not_equal' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_greater_than' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_greater_than_or_equal_to' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_less_than' => [ - 'expected_type' => 'number' + 'expected_type' => 'number', ], 'content_length_less_than_or_equal_to' => [ - 'expected_type' => 'number' - ] - ] + 'expected_type' => 'number', + ], + ], ], 'checkbox' => [ 'comparators' => [ @@ -295,18 +294,18 @@ class FormPropertyLogicRule implements Rule, DataAwareRule 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'does_not_equal' => [ 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], - ] + ], ], 'select' => [ 'comparators' => [ @@ -320,17 +319,17 @@ class FormPropertyLogicRule implements Rule, DataAwareRule 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'is_not_empty' => [ 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] - ] - ] + 'values' => [true], + ], + ], + ], ], 'multi_select' => [ 'comparators' => [ @@ -338,119 +337,119 @@ class FormPropertyLogicRule implements Rule, DataAwareRule 'expected_type' => ['object', 'string'], 'format' => [ 'type' => 'uuid', - ] + ], ], 'does_not_contain' => [ 'expected_type' => ['object', 'string'], 'format' => [ 'type' => 'uuid', - ] + ], ], 'is_empty' => [ 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'is_not_empty' => [ 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] - ] - ] + 'values' => [true], + ], + ], + ], ], 'date' => [ 'comparators' => [ 'equals' => [ 'expected_type' => 'string', 'format' => [ - 'type' => 'date' - ] + 'type' => 'date', + ], ], 'before' => [ 'expected_type' => 'string', 'format' => [ - 'type' => 'date' - ] + 'type' => 'date', + ], ], 'after' => [ 'expected_type' => 'string', 'format' => [ - 'type' => 'date' - ] + 'type' => 'date', + ], ], 'on_or_before' => [ 'expected_type' => 'string', 'format' => [ - 'type' => 'date' - ] + 'type' => 'date', + ], ], 'on_or_after' => [ 'expected_type' => 'string', 'format' => [ - 'type' => 'date' - ] + 'type' => 'date', + ], ], 'is_empty' => [ 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'is_not_empty' => [ 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'past_week' => [ 'expected_type' => 'object', 'format' => [ 'type' => 'empty', - 'values' => '{}' - ] + 'values' => '{}', + ], ], 'past_month' => [ 'expected_type' => 'object', 'format' => [ 'type' => 'empty', - 'values' => '{}' - ] + 'values' => '{}', + ], ], 'past_year' => [ 'expected_type' => 'object', 'format' => [ 'type' => 'empty', - 'values' => '{}' - ] + 'values' => '{}', + ], ], 'next_week' => [ 'expected_type' => 'object', 'format' => [ 'type' => 'empty', - 'values' => '{}' - ] + 'values' => '{}', + ], ], 'next_month' => [ 'expected_type' => 'object', 'format' => [ 'type' => 'empty', - 'values' => '{}' - ] + 'values' => '{}', + ], ], 'next_year' => [ 'expected_type' => 'object', 'format' => [ 'type' => 'empty', - 'values' => '{}' - ] - ] - ] + 'values' => '{}', + ], + ], + ], ], 'files' => [ 'comparators' => [ @@ -458,56 +457,65 @@ class FormPropertyLogicRule implements Rule, DataAwareRule 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] + 'values' => [true], + ], ], 'is_not_empty' => [ 'expected_type' => 'boolean', 'format' => [ 'type' => 'enum', - 'values' => [true] - ] - ] - ] + 'values' => [true], + ], + ], + ], ], ]; private $isConditionCorrect = true; + private $isActionCorrect = true; + private $conditionErrors = []; + private $field = []; + private $data = []; private function checkBaseCondition($condition) { - if (!isset($condition['value'])) { + if (! isset($condition['value'])) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'missing condition body'; + return; } - if (!isset($condition['value']['property_meta'])) { + if (! isset($condition['value']['property_meta'])) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'missing condition property'; + return; } - if (!isset($condition['value']['property_meta']['type'])) { + if (! isset($condition['value']['property_meta']['type'])) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'missing condition property type'; + return; } - if (!isset($condition['value']['operator'])) { + if (! isset($condition['value']['operator'])) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'missing condition operator'; + return; } - if (!isset($condition['value']['value'])) { + if (! isset($condition['value']['value'])) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'missing condition value'; + return; } @@ -515,15 +523,17 @@ class FormPropertyLogicRule implements Rule, DataAwareRule $operator = $condition['value']['operator']; $value = $condition['value']['value']; - if (!isset(self::CONDITION_MAPPING[$typeField])) { + if (! isset(self::CONDITION_MAPPING[$typeField])) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'configuration not found for condition type'; + return; } - if (!isset(self::CONDITION_MAPPING[$typeField]['comparators'][$operator])) { + if (! isset(self::CONDITION_MAPPING[$typeField]['comparators'][$operator])) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'configuration not found for condition operator'; + return; } @@ -536,11 +546,11 @@ class FormPropertyLogicRule implements Rule, DataAwareRule $foundCorrectType = true; } } - if (!$foundCorrectType) { + if (! $foundCorrectType) { $this->isConditionCorrect = false; } } else { - if (!$this->valueHasCorrectType($type, $value)) { + if (! $this->valueHasCorrectType($type, $value)) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'wrong type of condition value'; } @@ -551,12 +561,13 @@ class FormPropertyLogicRule implements Rule, DataAwareRule { if ( ($type === 'string' && gettype($value) !== 'string') || - ($type === 'boolean' && !is_bool($value)) || - ($type === 'number' && !is_numeric($value)) || - ($type === 'object' && !is_array($value)) + ($type === 'boolean' && ! is_bool($value)) || + ($type === 'number' && ! is_numeric($value)) || + ($type === 'object' && ! is_array($value)) ) { return false; } + return true; } @@ -566,25 +577,28 @@ class FormPropertyLogicRule implements Rule, DataAwareRule if (($conditions['operatorIdentifier'] !== 'and') && ($conditions['operatorIdentifier'] !== 'or')) { $this->conditionErrors[] = 'missing operator'; $this->isConditionCorrect = false; + return; } if (isset($conditions['operatorIdentifier']['children'])) { $this->conditionErrors[] = 'extra condition'; $this->isConditionCorrect = false; + return; } - if (!is_array($conditions['children'])) { + if (! is_array($conditions['children'])) { $this->conditionErrors[] = 'wrong sub-condition type'; $this->isConditionCorrect = false; + return; } foreach ($conditions['children'] as &$child) { $this->checkConditions($child); } - } else if (isset($conditions['identifier'])) { + } elseif (isset($conditions['identifier'])) { $this->checkBaseCondition($conditions); } } @@ -592,12 +606,12 @@ class FormPropertyLogicRule implements Rule, DataAwareRule private function checkActions($actions) { if (is_array($actions) && count($actions) > 0) { - foreach($actions as $val){ - if (!in_array($val, static::ACTIONS_VALUES) || - (in_array($this->field["type"], ['nf-text', 'nf-code', 'nf-page-break', 'nf-divider', 'nf-image']) && !in_array($val, ['hide-block', 'show-block'])) || - (isset($this->field["hidden"]) && $this->field["hidden"] && !in_array($val, ['show-block', 'require-answer'])) || - (isset($this->field["required"]) && $this->field["required"] && !in_array($val, ['make-it-optional', 'hide-block', 'disable-block'])) || - (isset($this->field["disabled"]) && $this->field["disabled"] && !in_array($val, ['enable-block', 'require-answer', 'make-it-optional'])) + foreach ($actions as $val) { + if (! in_array($val, static::ACTIONS_VALUES) || + (in_array($this->field['type'], ['nf-text', 'nf-code', 'nf-page-break', 'nf-divider', 'nf-image']) && ! in_array($val, ['hide-block', 'show-block'])) || + (isset($this->field['hidden']) && $this->field['hidden'] && ! in_array($val, ['show-block', 'require-answer'])) || + (isset($this->field['required']) && $this->field['required'] && ! in_array($val, ['make-it-optional', 'hide-block', 'disable-block'])) || + (isset($this->field['disabled']) && $this->field['disabled'] && ! in_array($val, ['enable-block', 'require-answer', 'make-it-optional'])) ) { $this->isActionCorrect = false; break; @@ -618,28 +632,27 @@ class FormPropertyLogicRule implements Rule, DataAwareRule public function passes($attribute, $value) { $this->setProperty($attribute); - if(isset($value["conditions"])){ - $this->checkConditions($value["conditions"]); + if (isset($value['conditions'])) { + $this->checkConditions($value['conditions']); $this->checkActions($value['actions'] ?? null); } - return ($this->isConditionCorrect && $this->isActionCorrect); + return $this->isConditionCorrect && $this->isActionCorrect; } /** * Get the validation error message. - * */ public function message() { $message = null; if (! $this->isConditionCorrect) { $message = 'The logic conditions for '.$this->field['name'].' are not complete.'; - } else if (! $this->isActionCorrect) { + } elseif (! $this->isActionCorrect) { $message = 'The logic actions for '.$this->field['name'].' are not valid.'; } if (count($this->conditionErrors) > 0) { - return $message . ' Error detail(s): '.implode(', ', $this->conditionErrors); + return $message.' Error detail(s): '.implode(', ', $this->conditionErrors); } return $message; diff --git a/app/Rules/OneEmailPerLine.php b/app/Rules/OneEmailPerLine.php index 20b0932..f1792d1 100644 --- a/app/Rules/OneEmailPerLine.php +++ b/app/Rules/OneEmailPerLine.php @@ -25,13 +25,16 @@ class OneEmailPerLine implements Rule */ public function passes($attribute, $value) { - if ($value === null || empty(trim($value))) return true; + if ($value === null || empty(trim($value))) { + return true; + } foreach (preg_split("/\r\n|\n|\r/", $value) as $email) { $email = trim($email); - if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { + if (! filter_var($email, FILTER_VALIDATE_EMAIL)) { return false; } } + return true; } diff --git a/app/Rules/StorageFile.php b/app/Rules/StorageFile.php index b7df2eb..2a0a382 100644 --- a/app/Rules/StorageFile.php +++ b/app/Rules/StorageFile.php @@ -3,11 +3,11 @@ namespace App\Rules; use App\Http\Controllers\Forms\PublicFormController; +use App\Models\Forms\Form; use App\Service\Storage\StorageFileNameParser; use Illuminate\Contracts\Validation\Rule; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; -use App\Models\Forms\Form; class StorageFile implements Rule { @@ -19,7 +19,6 @@ class StorageFile implements Rule public array $fileTypes; /** - * @param int $maxSize * @param string[] $fileTypes */ public function __construct(int $maxSize, array $fileTypes = [], public ?Form $form = null) @@ -36,42 +35,44 @@ class StorageFile implements Rule * * @param string $attribute * @param mixed $value - * @return bool */ public function passes($attribute, $value): bool { // If full path then no need to validate - if (filter_var($value, FILTER_VALIDATE_URL) !== FALSE) { + if (filter_var($value, FILTER_VALIDATE_URL) !== false) { return true; } // This is use when updating a record, and file uploads aren't changed. - if($this->form){ + if ($this->form) { $newPath = Str::of(PublicFormController::FILE_UPLOAD_PATH)->replace('?', $this->form->id); - if(Storage::exists($newPath.'/'.$value)){ + if (Storage::exists($newPath.'/'.$value)) { return true; } } $fileNameParser = StorageFileNameParser::parse($value); - if (!$uuid = $fileNameParser->uuid) { + if (! $uuid = $fileNameParser->uuid) { return false; } $filePath = PublicFormController::TMP_FILE_UPLOAD_PATH.$uuid; - if (!Storage::exists($filePath)) { + if (! Storage::exists($filePath)) { return false; } if (Storage::size($filePath) > $this->maxSize) { $this->error = 'File is too large.'; + return false; } if (count($this->fileTypes) > 0) { - $this->error = 'Incorrect file type. Allowed only: '.implode(",", $this->fileTypes); + $this->error = 'Incorrect file type. Allowed only: '.implode(',', $this->fileTypes); + return in_array($fileNameParser->extension, $this->fileTypes); } + return true; } diff --git a/app/Rules/ValidHCaptcha.php b/app/Rules/ValidHCaptcha.php index f6522de..0f9b732 100644 --- a/app/Rules/ValidHCaptcha.php +++ b/app/Rules/ValidHCaptcha.php @@ -7,7 +7,7 @@ use Illuminate\Support\Facades\Http; class ValidHCaptcha implements ImplicitRule { - const H_CAPTCHA_VERIFY_URL = "https://hcaptcha.com/siteverify"; + public const H_CAPTCHA_VERIFY_URL = 'https://hcaptcha.com/siteverify'; private $error = 'Invalid CAPTCHA. Please prove you\'re not a bot.'; @@ -21,13 +21,14 @@ class ValidHCaptcha implements ImplicitRule public function passes($attribute, $value) { if (empty($value)) { - $this->error = "Please complete the captcha."; + $this->error = 'Please complete the captcha.'; + return false; } return Http::asForm()->post(self::H_CAPTCHA_VERIFY_URL, [ 'secret' => config('services.h_captcha.secret_key'), - 'response' => $value + 'response' => $value, ])->json('success'); } diff --git a/app/Rules/ValidPhoneInputRule.php b/app/Rules/ValidPhoneInputRule.php index 812beb1..a52f8fe 100644 --- a/app/Rules/ValidPhoneInputRule.php +++ b/app/Rules/ValidPhoneInputRule.php @@ -3,25 +3,24 @@ namespace App\Rules; use Illuminate\Contracts\Validation\Rule; -use Illuminate\Support\Str; class ValidPhoneInputRule implements Rule { - public ?int $reason = 0; public function passes($attribute, $value) { - if (!is_string($value) || !$value) { + if (! is_string($value) || ! $value) { return false; } try { - if(ctype_alpha(substr($value, 0, 2))){ // First 2 will be country code + if (ctype_alpha(substr($value, 0, 2))) { // First 2 will be country code $value = substr($value, 2); } $phoneUtil = \libphonenumber\PhoneNumberUtil::getInstance(); $phone = $phoneUtil->parse($value); $this->reason = $phoneUtil->isPossibleNumberWithReason($phone); + return $this->reason === \libphonenumber\ValidationResult::IS_POSSIBLE; } catch (\Exception $e) { return false; diff --git a/app/Service/Forms/FormCleaner.php b/app/Service/Forms/FormCleaner.php index fc2889e..d609eae 100644 --- a/app/Service/Forms/FormCleaner.php +++ b/app/Service/Forms/FormCleaner.php @@ -1,22 +1,23 @@ null, 'editable_submissions' => false, 'custom_code' => null, - 'seo_meta' => [] + 'seo_meta' => [], ]; private array $fieldDefaults = [ @@ -45,24 +46,23 @@ class FormCleaner private array $cleaningMessages = [ // For form - 'notifies' => "Email notification were disabled.", - 'no_branding' => "OpenForm branding is not hidden.", - 'webhook_url' => "Webhook disabled.", + 'notifies' => 'Email notification were disabled.', + 'no_branding' => 'OpenForm branding is not hidden.', + 'webhook_url' => 'Webhook disabled.', 'database_fields_update' => 'Form submission will only create new records (no updates).', - 'slack_webhook_url' => "Slack webhook disabled.", - 'discord_webhook_url' => "Discord webhook disabled.", + 'slack_webhook_url' => 'Slack webhook disabled.', + 'discord_webhook_url' => 'Discord webhook disabled.', 'editable_submissions' => 'Users will not be able to edit their submissions.', 'custom_code' => 'Custom code was disabled', 'seo_meta' => 'Custom SEO was disabled', // For fields - 'file_upload' => "Link field is not a file upload.", + 'file_upload' => 'Link field is not a file upload.', 'custom_block' => 'The custom block was removed.', ]; /** * Returns form data after request ingestion - * @return array */ public function getData(): array { @@ -71,7 +71,6 @@ class FormCleaner /** * Returns true if at least one cleaning was done - * @return bool */ public function hasCleaned(): bool { @@ -89,6 +88,7 @@ class FormCleaner return $this->cleaningMessages[$cleaning]; }); } + return $cleaningMsgs; } @@ -106,7 +106,7 @@ class FormCleaner /** * Create form cleaner instance from existing form */ - public function processForm(Request $request, Form $form) : FormCleaner + public function processForm(Request $request, Form $form): FormCleaner { $data = (new FormResource($form))->toArray($request); $this->data = $this->commonCleaning($data); @@ -114,17 +114,19 @@ class FormCleaner return $this; } - private function isPro(Workspace $workspace) { + private function isPro(Workspace $workspace) + { return $workspace->is_pro; } /** * Dry run celanings + * * @param User|null $user */ - public function simulateCleaning(Workspace $workspace): FormCleaner + public function simulateCleaning(Workspace $workspace): FormCleaner { - if (!$this->isPro($workspace)) { + if (! $this->isPro($workspace)) { $this->data = $this->removeProFeatures($this->data, true); } @@ -133,12 +135,13 @@ class FormCleaner /** * Perform Cleanigns + * * @param User|null $user * @return $this|array */ public function performCleaning(Workspace $workspace): FormCleaner { - if (!$this->isPro($workspace)) { + if (! $this->isPro($workspace)) { $this->data = $this->removeProFeatures($this->data); } @@ -211,17 +214,17 @@ class FormCleaner $formVal = $this->cleanCustomKeys($key, $formVal); // Transform boolean values - $formVal = (($formVal === 0 || $formVal === "0") ? false : $formVal); - $formVal = (($formVal === 1 || $formVal === "1") ? true : $formVal); + $formVal = (($formVal === 0 || $formVal === '0') ? false : $formVal); + $formVal = (($formVal === 1 || $formVal === '1') ? true : $formVal); - if (!is_null($formVal) && $formVal !== $value) { - if (!isset($this->cleanings['form'])) { + if (! is_null($formVal) && $formVal !== $value) { + if (! isset($this->cleanings['form'])) { $this->cleanings['form'] = []; } $this->cleanings['form'][] = $key; // If not a simulation, do the cleaning - if (!$simulation) { + if (! $simulation) { Arr::set($data, $key, $value); } } @@ -233,7 +236,7 @@ class FormCleaner foreach ($defaults as $key => $value) { if (isset($data[$key]) && Arr::get($data, $key) !== $value) { $this->cleanings[$data['name']][] = $key; - if (!$simulation) { + if (! $simulation) { Arr::set($data, $key, $value); } } @@ -260,10 +263,10 @@ class FormCleaner $newVal[$k] = $val; } } + return $newVal; } return $formVal; } - } diff --git a/app/Service/Forms/FormLogicConditionChecker.php b/app/Service/Forms/FormLogicConditionChecker.php index 69a7938..0d95f6b 100644 --- a/app/Service/Forms/FormLogicConditionChecker.php +++ b/app/Service/Forms/FormLogicConditionChecker.php @@ -2,88 +2,95 @@ namespace App\Service\Forms; -use Mockery\Matcher\Any; - -use function PHPUnit\Framework\isEmpty; - class FormLogicConditionChecker { public function __construct(private ?array $conditions, private ?array $formData) { } - public static function conditionsMet(?array $conditions, array $formData): bool { + public static function conditionsMet(?array $conditions, array $formData): bool + { return (new self($conditions, $formData))->conditionsAreMet($conditions, $formData); } - private function conditionsAreMet(?array $conditions, array $formData): bool { - if (!$conditions) { + private function conditionsAreMet(?array $conditions, array $formData): bool + { + if (! $conditions) { return false; } // If it's not a group, just a single condition - if (!isset($conditions['operatorIdentifier'])) { + if (! isset($conditions['operatorIdentifier'])) { return $this->propertyConditionMet($conditions['value'], $formData[$conditions['value']['property_meta']['id']] ?? null); } if ($conditions['operatorIdentifier'] === 'and') { $isvalid = true; - foreach($conditions['children'] as $childrenCondition){ - if (!$this->conditionsMet($childrenCondition, $formData)) { + foreach ($conditions['children'] as $childrenCondition) { + if (! $this->conditionsMet($childrenCondition, $formData)) { $isvalid = false; break; } } + return $isvalid; - } else if ($conditions['operatorIdentifier'] === 'or') { + } elseif ($conditions['operatorIdentifier'] === 'or') { $isvalid = false; - foreach($conditions['children'] as $childrenCondition){ + foreach ($conditions['children'] as $childrenCondition) { if ($this->conditionsMet($childrenCondition, $formData)) { $isvalid = true; break; } } + return $isvalid; } - throw new \Exception('Unexcepted operatorIdentifier:'. $conditions['operatorIdentifier']); + throw new \Exception('Unexcepted operatorIdentifier:'.$conditions['operatorIdentifier']); } - private function propertyConditionMet(array $propertyCondition, $value): bool { + private function propertyConditionMet(array $propertyCondition, $value): bool + { switch ($propertyCondition['property_meta']['type']) { case 'text': case 'url': case 'email': case 'phone_number': - return $this->textConditionMet($propertyCondition, $value); + return $this->textConditionMet($propertyCondition, $value); case 'number': - return $this->numberConditionMet($propertyCondition, $value); + return $this->numberConditionMet($propertyCondition, $value); case 'checkbox': - return $this->checkboxConditionMet($propertyCondition, $value); + return $this->checkboxConditionMet($propertyCondition, $value); case 'select': - return $this->selectConditionMet($propertyCondition, $value); + return $this->selectConditionMet($propertyCondition, $value); case 'date': - return $this->dateConditionMet($propertyCondition, $value); + return $this->dateConditionMet($propertyCondition, $value); case 'multi_select': - return $this->multiSelectConditionMet($propertyCondition, $value); + return $this->multiSelectConditionMet($propertyCondition, $value); case 'files': - return $this->filesConditionMet($propertyCondition, $value); - } - return false; + return $this->filesConditionMet($propertyCondition, $value); + } + + return false; } - private function checkEquals ($condition, $fieldValue): bool { + private function checkEquals($condition, $fieldValue): bool + { return $condition['value'] === $fieldValue; } - private function checkContains ($condition, $fieldValue): bool { + private function checkContains($condition, $fieldValue): bool + { return ($fieldValue && is_array($fieldValue)) ? in_array($condition['value'], $fieldValue) : false; } - private function checkListContains ($condition, $fieldValue): bool { - if (is_null($fieldValue)) return false; + private function checkListContains($condition, $fieldValue): bool + { + if (is_null($fieldValue)) { + return false; + } - if (!is_array($fieldValue)) { + if (! is_array($fieldValue)) { return $this->checkEquals($condition, $fieldValue); } @@ -94,252 +101,305 @@ class FormLogicConditionChecker } } - private function checkStartsWith ($condition, $fieldValue): bool { + private function checkStartsWith($condition, $fieldValue): bool + { return str_starts_with($fieldValue, $condition['value']); } - private function checkEndsWith ($condition, $fieldValue): bool { + private function checkEndsWith($condition, $fieldValue): bool + { return str_ends_with($fieldValue, $condition['value']); } - private function checkIsEmpty ($condition, $fieldValue): bool { - if(is_array($fieldValue)){ + private function checkIsEmpty($condition, $fieldValue): bool + { + if (is_array($fieldValue)) { return count($fieldValue) === 0; } - return $fieldValue == '' || $fieldValue == null || !$fieldValue; + + return $fieldValue == '' || $fieldValue == null || ! $fieldValue; } - private function checkGreaterThan ($condition, $fieldValue): bool { - return ($condition['value'] && $fieldValue && (float)$fieldValue > (float)$condition['value']); + private function checkGreaterThan($condition, $fieldValue): bool + { + return $condition['value'] && $fieldValue && (float) $fieldValue > (float) $condition['value']; } - private function checkGreaterThanEqual ($condition, $fieldValue): bool { - return ($condition['value'] && $fieldValue && (float)$fieldValue >= (float)$condition['value']); + private function checkGreaterThanEqual($condition, $fieldValue): bool + { + return $condition['value'] && $fieldValue && (float) $fieldValue >= (float) $condition['value']; } - private function checkLessThan ($condition, $fieldValue): bool { - return ($condition['value'] && $fieldValue && (float)$fieldValue < (float)$condition['value']); + private function checkLessThan($condition, $fieldValue): bool + { + return $condition['value'] && $fieldValue && (float) $fieldValue < (float) $condition['value']; } - private function checkLessThanEqual ($condition, $fieldValue): bool { - return ($condition['value'] && $fieldValue && (float)$fieldValue <= (float)$condition['value']); + private function checkLessThanEqual($condition, $fieldValue): bool + { + return $condition['value'] && $fieldValue && (float) $fieldValue <= (float) $condition['value']; } - private function checkBefore ($condition, $fieldValue): bool { - return ($condition['value'] && $fieldValue && $fieldValue > $condition['value']); + private function checkBefore($condition, $fieldValue): bool + { + return $condition['value'] && $fieldValue && $fieldValue > $condition['value']; } - private function checkAfter ($condition, $fieldValue): bool { - return ($condition['value'] && $fieldValue && $fieldValue < $condition['value']); + private function checkAfter($condition, $fieldValue): bool + { + return $condition['value'] && $fieldValue && $fieldValue < $condition['value']; } - private function checkOnOrBefore ($condition, $fieldValue): bool { - return ($condition['value'] && $fieldValue && $fieldValue >= $condition['value']); + private function checkOnOrBefore($condition, $fieldValue): bool + { + return $condition['value'] && $fieldValue && $fieldValue >= $condition['value']; } - private function checkOnOrAfter ($condition, $fieldValue): bool { - return ($condition['value'] && $fieldValue && $fieldValue <= $condition['value']); + private function checkOnOrAfter($condition, $fieldValue): bool + { + return $condition['value'] && $fieldValue && $fieldValue <= $condition['value']; } - private function checkPastWeek ($condition, $fieldValue): bool { - if(!$fieldValue) return false; + private function checkPastWeek($condition, $fieldValue): bool + { + if (! $fieldValue) { + return false; + } $fieldDate = date('Y-m-d', strtotime($fieldValue)); - return ($fieldDate <= now()->toDateString() && $fieldDate >= now()->subDays(7)->toDateString()); + + return $fieldDate <= now()->toDateString() && $fieldDate >= now()->subDays(7)->toDateString(); } - private function checkPastMonth ($condition, $fieldValue): bool { - if(!$fieldValue) return false; + private function checkPastMonth($condition, $fieldValue): bool + { + if (! $fieldValue) { + return false; + } $fieldDate = date('Y-m-d', strtotime($fieldValue)); - return ($fieldDate <= now()->toDateString() && $fieldDate >= now()->subMonths(1)->toDateString()); + + return $fieldDate <= now()->toDateString() && $fieldDate >= now()->subMonths(1)->toDateString(); } - private function checkPastYear ($condition, $fieldValue): bool { - if(!$fieldValue) return false; + private function checkPastYear($condition, $fieldValue): bool + { + if (! $fieldValue) { + return false; + } $fieldDate = date('Y-m-d', strtotime($fieldValue)); - return ($fieldDate <= now()->toDateString() && $fieldDate >= now()->subYears(1)->toDateString()); + + return $fieldDate <= now()->toDateString() && $fieldDate >= now()->subYears(1)->toDateString(); } - private function checkNextWeek ($condition, $fieldValue): bool { - if(!$fieldValue) return false; + private function checkNextWeek($condition, $fieldValue): bool + { + if (! $fieldValue) { + return false; + } $fieldDate = date('Y-m-d', strtotime($fieldValue)); - return ($fieldDate >= now()->toDateString() && $fieldDate <= now()->addDays(7)->toDateString()); + + return $fieldDate >= now()->toDateString() && $fieldDate <= now()->addDays(7)->toDateString(); } - private function checkNextMonth ($condition, $fieldValue): bool { - if(!$fieldValue) return false; + private function checkNextMonth($condition, $fieldValue): bool + { + if (! $fieldValue) { + return false; + } $fieldDate = date('Y-m-d', strtotime($fieldValue)); - return ($fieldDate >= now()->toDateString() && $fieldDate <= now()->addMonths(1)->toDateString()); + + return $fieldDate >= now()->toDateString() && $fieldDate <= now()->addMonths(1)->toDateString(); } - private function checkNextYear ($condition, $fieldValue): bool { - if(!$fieldValue) return false; + private function checkNextYear($condition, $fieldValue): bool + { + if (! $fieldValue) { + return false; + } $fieldDate = date('Y-m-d', strtotime($fieldValue)); - return ($fieldDate >= now()->toDateString() && $fieldDate <= now()->addYears(1)->toDateString()); + + return $fieldDate >= now()->toDateString() && $fieldDate <= now()->addYears(1)->toDateString(); } - private function checkLength ($condition, $fieldValue, $operator = '==='): bool { - if(!$fieldValue || strlen($fieldValue) === 0) return false; + private function checkLength($condition, $fieldValue, $operator = '==='): bool + { + if (! $fieldValue || strlen($fieldValue) === 0) { + return false; + } switch ($operator) { - case '===': - return strlen($fieldValue) === (int)$condition['value']; - case '!==': - return strlen($fieldValue) !== (int)$condition['value']; - case '>': - return strlen($fieldValue) > (int)$condition['value']; - case '>=': - return strlen($fieldValue) >= (int)$condition['value']; - case '<': - return strlen($fieldValue) < (int)$condition['value']; - case '<=': - return strlen($fieldValue) <= (int)$condition['value']; + case '===': + return strlen($fieldValue) === (int) $condition['value']; + case '!==': + return strlen($fieldValue) !== (int) $condition['value']; + case '>': + return strlen($fieldValue) > (int) $condition['value']; + case '>=': + return strlen($fieldValue) >= (int) $condition['value']; + case '<': + return strlen($fieldValue) < (int) $condition['value']; + case '<=': + return strlen($fieldValue) <= (int) $condition['value']; } + return false; } - - private function textConditionMet (array $propertyCondition, $value): bool { + private function textConditionMet(array $propertyCondition, $value): bool + { switch ($propertyCondition['operator']) { - case 'equals': - return $this->checkEquals($propertyCondition, $value); - case 'does_not_equal': - return !$this->checkEquals($propertyCondition, $value); - case 'contains': - return $this->checkContains($propertyCondition, $value); - case 'does_not_contain': - return !$this->checkContains($propertyCondition, $value); - case 'starts_with': - return $this->checkStartsWith($propertyCondition, $value); - case 'ends_with': - return $this->checkEndsWith($propertyCondition, $value); - case 'is_empty': - return $this->checkIsEmpty($propertyCondition, $value); - case 'is_not_empty': - return !$this->checkIsEmpty($propertyCondition, $value); - case 'content_length_equals': - return $this->checkLength($propertyCondition, $value, '==='); - case 'content_length_does_not_equal': - return $this->checkLength($propertyCondition, $value, '!=='); - case 'content_length_greater_than': - return $this->checkLength($propertyCondition, $value, '>'); - case 'content_length_greater_than_or_equal_to': - return $this->checkLength($propertyCondition, $value, '>='); - case 'content_length_less_than': - return $this->checkLength($propertyCondition, $value, '<'); - case 'content_length_less_than_or_equal_to': - return $this->checkLength($propertyCondition, $value, '<='); + case 'equals': + return $this->checkEquals($propertyCondition, $value); + case 'does_not_equal': + return ! $this->checkEquals($propertyCondition, $value); + case 'contains': + return $this->checkContains($propertyCondition, $value); + case 'does_not_contain': + return ! $this->checkContains($propertyCondition, $value); + case 'starts_with': + return $this->checkStartsWith($propertyCondition, $value); + case 'ends_with': + return $this->checkEndsWith($propertyCondition, $value); + case 'is_empty': + return $this->checkIsEmpty($propertyCondition, $value); + case 'is_not_empty': + return ! $this->checkIsEmpty($propertyCondition, $value); + case 'content_length_equals': + return $this->checkLength($propertyCondition, $value, '==='); + case 'content_length_does_not_equal': + return $this->checkLength($propertyCondition, $value, '!=='); + case 'content_length_greater_than': + return $this->checkLength($propertyCondition, $value, '>'); + case 'content_length_greater_than_or_equal_to': + return $this->checkLength($propertyCondition, $value, '>='); + case 'content_length_less_than': + return $this->checkLength($propertyCondition, $value, '<'); + case 'content_length_less_than_or_equal_to': + return $this->checkLength($propertyCondition, $value, '<='); } + return false; } - private function numberConditionMet (array $propertyCondition, $value): bool { + private function numberConditionMet(array $propertyCondition, $value): bool + { switch ($propertyCondition['operator']) { - case 'equals': - return $this->checkEquals($propertyCondition, $value); - case 'does_not_equal': - return !$this->checkEquals($propertyCondition, $value); - case 'greater_than': - return $this->checkGreaterThan($propertyCondition, $value); - case 'less_than': - return $this->checkLessThan($propertyCondition, $value); - case 'greater_than_or_equal_to': - return $this->checkGreaterThanEqual($propertyCondition, $value); - case 'less_than_or_equal_to': - return $this->checkLessThanEqual($propertyCondition, $value); - case 'is_empty': - return $this->checkIsEmpty($propertyCondition, $value); - case 'is_not_empty': - return !$this->checkIsEmpty($propertyCondition, $value); - case 'content_length_equals': - return $this->checkLength($propertyCondition, $value, '==='); - case 'content_length_does_not_equal': - return $this->checkLength($propertyCondition, $value, '!=='); - case 'content_length_greater_than': - return $this->checkLength($propertyCondition, $value, '>'); - case 'content_length_greater_than_or_equal_to': - return $this->checkLength($propertyCondition, $value, '>='); - case 'content_length_less_than': - return $this->checkLength($propertyCondition, $value, '<'); - case 'content_length_less_than_or_equal_to': - return $this->checkLength($propertyCondition, $value, '<='); + case 'equals': + return $this->checkEquals($propertyCondition, $value); + case 'does_not_equal': + return ! $this->checkEquals($propertyCondition, $value); + case 'greater_than': + return $this->checkGreaterThan($propertyCondition, $value); + case 'less_than': + return $this->checkLessThan($propertyCondition, $value); + case 'greater_than_or_equal_to': + return $this->checkGreaterThanEqual($propertyCondition, $value); + case 'less_than_or_equal_to': + return $this->checkLessThanEqual($propertyCondition, $value); + case 'is_empty': + return $this->checkIsEmpty($propertyCondition, $value); + case 'is_not_empty': + return ! $this->checkIsEmpty($propertyCondition, $value); + case 'content_length_equals': + return $this->checkLength($propertyCondition, $value, '==='); + case 'content_length_does_not_equal': + return $this->checkLength($propertyCondition, $value, '!=='); + case 'content_length_greater_than': + return $this->checkLength($propertyCondition, $value, '>'); + case 'content_length_greater_than_or_equal_to': + return $this->checkLength($propertyCondition, $value, '>='); + case 'content_length_less_than': + return $this->checkLength($propertyCondition, $value, '<'); + case 'content_length_less_than_or_equal_to': + return $this->checkLength($propertyCondition, $value, '<='); } + return false; } - private function checkboxConditionMet (array $propertyCondition, $value): bool { + private function checkboxConditionMet(array $propertyCondition, $value): bool + { switch ($propertyCondition['operator']) { - case 'equals': - return $this->checkEquals($propertyCondition, $value); - case 'does_not_equal': - return !$this->checkEquals($propertyCondition, $value); + case 'equals': + return $this->checkEquals($propertyCondition, $value); + case 'does_not_equal': + return ! $this->checkEquals($propertyCondition, $value); } + return false; } - private function selectConditionMet (array $propertyCondition, $value): bool { + private function selectConditionMet(array $propertyCondition, $value): bool + { switch ($propertyCondition['operator']) { - case 'equals': - return $this->checkEquals($propertyCondition, $value); - case 'does_not_equal': - return !$this->checkEquals($propertyCondition, $value); - case 'is_empty': - return $this->checkIsEmpty($propertyCondition, $value); - case 'is_not_empty': - return !$this->checkIsEmpty($propertyCondition, $value); + case 'equals': + return $this->checkEquals($propertyCondition, $value); + case 'does_not_equal': + return ! $this->checkEquals($propertyCondition, $value); + case 'is_empty': + return $this->checkIsEmpty($propertyCondition, $value); + case 'is_not_empty': + return ! $this->checkIsEmpty($propertyCondition, $value); } + return false; } - private function dateConditionMet (array $propertyCondition, $value): bool { + private function dateConditionMet(array $propertyCondition, $value): bool + { switch ($propertyCondition['operator']) { - case 'equals': - return $this->checkEquals($propertyCondition, $value); - case 'before': - return $this->checkBefore($propertyCondition, $value); - case 'after': - return $this->checkAfter($propertyCondition, $value); - case 'on_or_before': - return $this->checkOnOrBefore($propertyCondition, $value); - case 'on_or_after': - return $this->checkOnOrAfter($propertyCondition, $value); - case 'is_empty': - return $this->checkIsEmpty($propertyCondition, $value); - case 'past_week': - return $this->checkPastWeek($propertyCondition, $value); - case 'past_month': - return $this->checkPastMonth($propertyCondition, $value); - case 'past_year': - return $this->checkPastYear($propertyCondition, $value); - case 'next_week': - return $this->checkNextWeek($propertyCondition, $value); - case 'next_month': - return $this->checkNextMonth($propertyCondition, $value); - case 'next_year': - return $this->checkNextYear($propertyCondition, $value); + case 'equals': + return $this->checkEquals($propertyCondition, $value); + case 'before': + return $this->checkBefore($propertyCondition, $value); + case 'after': + return $this->checkAfter($propertyCondition, $value); + case 'on_or_before': + return $this->checkOnOrBefore($propertyCondition, $value); + case 'on_or_after': + return $this->checkOnOrAfter($propertyCondition, $value); + case 'is_empty': + return $this->checkIsEmpty($propertyCondition, $value); + case 'past_week': + return $this->checkPastWeek($propertyCondition, $value); + case 'past_month': + return $this->checkPastMonth($propertyCondition, $value); + case 'past_year': + return $this->checkPastYear($propertyCondition, $value); + case 'next_week': + return $this->checkNextWeek($propertyCondition, $value); + case 'next_month': + return $this->checkNextMonth($propertyCondition, $value); + case 'next_year': + return $this->checkNextYear($propertyCondition, $value); } + return false; } - private function multiSelectConditionMet (array $propertyCondition, $value): bool { + private function multiSelectConditionMet(array $propertyCondition, $value): bool + { switch ($propertyCondition['operator']) { - case 'contains': - return $this->checkListContains($propertyCondition, $value); - case 'does_not_contain': - return !$this->checkListContains($propertyCondition, $value); - case 'is_empty': - return $this->checkIsEmpty($propertyCondition, $value); - case 'is_not_empty': - return !$this->checkIsEmpty($propertyCondition, $value); + case 'contains': + return $this->checkListContains($propertyCondition, $value); + case 'does_not_contain': + return ! $this->checkListContains($propertyCondition, $value); + case 'is_empty': + return $this->checkIsEmpty($propertyCondition, $value); + case 'is_not_empty': + return ! $this->checkIsEmpty($propertyCondition, $value); } + return false; } - private function filesConditionMet (array $propertyCondition, $value): bool { + private function filesConditionMet(array $propertyCondition, $value): bool + { switch ($propertyCondition['operator']) { - case 'is_empty': - return $this->checkIsEmpty($propertyCondition, $value); - case 'is_not_empty': - return !$this->checkIsEmpty($propertyCondition, $value); + case 'is_empty': + return $this->checkIsEmpty($propertyCondition, $value); + case 'is_not_empty': + return ! $this->checkIsEmpty($propertyCondition, $value); } + return false; } } diff --git a/app/Service/Forms/FormLogicPropertyResolver.php b/app/Service/Forms/FormLogicPropertyResolver.php index b57c4ff..9319072 100644 --- a/app/Service/Forms/FormLogicPropertyResolver.php +++ b/app/Service/Forms/FormLogicPropertyResolver.php @@ -2,13 +2,12 @@ namespace App\Service\Forms; -use App\Service\Forms\FormLogicConditionChecker; - class FormLogicPropertyResolver { - private $property = []; + private $formData = []; + private $logic = false; public function __construct(private array $prop, private array $values) @@ -30,18 +29,18 @@ class FormLogicPropertyResolver public function shouldBeRequired(): bool { - if(!isset($this->property['required'])){ + if (! isset($this->property['required'])) { return false; } - if (!$this->logic) { + if (! $this->logic) { return $this->property['required']; } $conditionsMet = FormLogicConditionChecker::conditionsMet($this->logic['conditions'], $this->formData); if ($conditionsMet && $this->property['required'] && count($this->logic['actions']) > 0 && (in_array('make-it-optional', $this->logic['actions']) || in_array('hide-block', $this->logic['actions']))) { return false; - } else if ($conditionsMet && !$this->property['required'] && count($this->logic['actions']) > 0 && in_array('require-answer', $this->logic['actions'])) { + } elseif ($conditionsMet && ! $this->property['required'] && count($this->logic['actions']) > 0 && in_array('require-answer', $this->logic['actions'])) { return true; } else { return $this->property['required']; @@ -54,14 +53,14 @@ class FormLogicPropertyResolver return false; } - if (!$this->logic) { + if (! $this->logic) { return $this->property['hidden']; } $conditionsMet = FormLogicConditionChecker::conditionsMet($this->logic['conditions'], $this->formData); if ($conditionsMet && $this->property['hidden'] && count($this->logic['actions']) > 0 && in_array('show-block', $this->logic['actions'])) { return false; - } elseif ($conditionsMet && !$this->property['hidden'] && count($this->logic['actions']) > 0 && in_array('hide-block', $this->logic['actions'])) { + } elseif ($conditionsMet && ! $this->property['hidden'] && count($this->logic['actions']) > 0 && in_array('hide-block', $this->logic['actions'])) { return true; } else { return $this->property['hidden']; diff --git a/app/Service/Forms/FormSubmissionFormatter.php b/app/Service/Forms/FormSubmissionFormatter.php index 8fbab0d..d1690cb 100644 --- a/app/Service/Forms/FormSubmissionFormatter.php +++ b/app/Service/Forms/FormSubmissionFormatter.php @@ -1,24 +1,22 @@ links for emails and urls + * * @var bool */ private $createLinks = false; /** * If true, serialize arrays + * * @var bool */ private $outputStringsOnly = false; @@ -38,42 +36,48 @@ class FormSubmissionFormatter public function __construct(private Form $form, private array $formData) { - $this->initIdFormData(); + $this->initIdFormData(); } public function createLinks() { $this->createLinks = true; + return $this; } public function showHiddenFields() { $this->showHiddenFields = true; + return $this; } public function outputStringsOnly() { $this->outputStringsOnly = true; + return $this; } public function setEmptyForNoValue() { $this->setEmptyForNoValue = true; + return $this; } public function showRemovedFields() { $this->showRemovedFields = true; + return $this; } public function useSignedUrlForFiles() { $this->useSignedUrlForFiles = true; + return $this; } @@ -90,40 +94,41 @@ class FormSubmissionFormatter $removeFields = collect($this->form->removed_properties)->map(function ($field) { return [ ...$field, - 'removed' => true + 'removed' => true, ]; }); if ($this->showRemovedFields) { $fields = $fields->merge($removeFields); } $fields = $fields->filter(function ($field) { - return !in_array($field['type'],['nf-text', 'nf-code', 'nf-page-break', 'nf-divider', 'nf-image']); + return ! in_array($field['type'], ['nf-text', 'nf-code', 'nf-page-break', 'nf-divider', 'nf-image']); })->values(); $returnArray = []; foreach ($fields as $field) { - if (in_array($field['id'],['nf-text', 'nf-code', 'nf-page-break', 'nf-divider', 'nf-image'])) { + if (in_array($field['id'], ['nf-text', 'nf-code', 'nf-page-break', 'nf-divider', 'nf-image'])) { continue; } - if($field['removed'] ?? false) { - $field['name'] = $field['name']." (deleted)"; + if ($field['removed'] ?? false) { + $field['name'] = $field['name'].' (deleted)'; } // Add ID to avoid name clashes $field['name'] = $field['name'].' ('.\Str::of($field['id']).')'; // If not present skip - if (!isset($data[$field['id']])) { + if (! isset($data[$field['id']])) { if ($this->setEmptyForNoValue) { $returnArray[$field['name']] = ''; } + continue; } // If hide hidden fields - if (!$this->showHiddenFields) { + if (! $this->showHiddenFields) { if (FormLogicPropertyResolver::isHidden($field, $this->idFormData ?? [])) { continue; } @@ -143,7 +148,8 @@ class FormSubmissionFormatter } elseif ($field['type'] == 'files') { if ($this->outputStringsOnly) { $formId = $this->form->id; - $returnArray[$field['name']] = implode(', ', + $returnArray[$field['name']] = implode( + ', ', collect($data[$field['id']])->map(function ($file) use ($formId) { return $this->getFileUrl($formId, $file); })->toArray() @@ -151,11 +157,11 @@ class FormSubmissionFormatter } else { $formId = $this->form->id; $returnArray[$field['name']] = collect($data[$field['id']])->map(function ($file) use ($formId) { - return [ - 'file_url' => $this->getFileUrl($formId, $file), - 'file_name' => $file, - ]; - }); + return [ + 'file_url' => $this->getFileUrl($formId, $file), + 'file_name' => $file, + ]; + }); } } else { if (is_array($data[$field['id']])) { @@ -164,6 +170,7 @@ class FormSubmissionFormatter $returnArray[$field['name']] = $data[$field['id']]; } } + return $returnArray; } @@ -177,12 +184,12 @@ class FormSubmissionFormatter $fields = $this->form->properties; $transformedFields = []; foreach ($fields as $field) { - if (!isset($field['id']) || !isset($data[$field['id']])) { + if (! isset($field['id']) || ! isset($data[$field['id']])) { continue; } // If hide hidden fields - if (!$this->showHiddenFields) { + if (! $this->showHiddenFields) { if (FormLogicPropertyResolver::isHidden($field, $this->idFormData)) { continue; } @@ -211,17 +218,19 @@ class FormSubmissionFormatter } elseif ($field['type'] == 'files') { if ($this->outputStringsOnly) { $formId = $this->form->id; - $field['value'] = implode(', ', + $field['value'] = implode( + ', ', collect($data[$field['id']])->map(function ($file) use ($formId) { - return $this->getFileUrl($formId, $file); + return $this->getFileUrl($formId, $file); })->toArray() ); $field['email_data'] = collect($data[$field['id']])->map(function ($file) use ($formId) { $splitText = explode('.', $file); + return [ - "unsigned_url" => route('open.forms.submissions.file', [$formId, $file]), - "signed_url" => $this->getFileUrl($formId, $file), - "label" => \Str::limit($file, 20, '[...].'.end($splitText)) + 'unsigned_url' => route('open.forms.submissions.file', [$formId, $file]), + 'signed_url' => $this->getFileUrl($formId, $file), + 'label' => \Str::limit($file, 20, '[...].'.end($splitText)), ]; })->toArray(); } else { @@ -243,10 +252,12 @@ class FormSubmissionFormatter } $transformedFields[] = $field; } + return $transformedFields; } - private function initIdFormData() { + private function initIdFormData() + { $formProperties = collect($this->form->properties); foreach ($this->formData as $key => $value) { $property = $formProperties->first(function ($item) use ($key) { @@ -262,7 +273,7 @@ class FormSubmissionFormatter { return $this->useSignedUrlForFiles ? \URL::signedRoute( 'open.forms.submissions.file', - [$formId, $file]) : route('open.forms.submissions.file', [$formId, $file]); + [$formId, $file] + ) : route('open.forms.submissions.file', [$formId, $file]); } - } diff --git a/app/Service/Forms/Webhooks/AbstractWebhookHandler.php b/app/Service/Forms/Webhooks/AbstractWebhookHandler.php index 4e404ff..1e7b565 100644 --- a/app/Service/Forms/Webhooks/AbstractWebhookHandler.php +++ b/app/Service/Forms/Webhooks/AbstractWebhookHandler.php @@ -4,8 +4,6 @@ namespace App\Service\Forms\Webhooks; use App\Models\Forms\Form; use App\Service\Forms\FormSubmissionFormatter; -use GuzzleHttp\Exception\ClientException; -use Illuminate\Support\Str; use Spatie\WebhookServer\WebhookCall; use Vinkla\Hashids\Facades\Hashids; @@ -21,14 +19,12 @@ abstract class AbstractWebhookHandler /** * Default webhook payload. Can be changed in child classes. - * @return array */ protected function getWebhookData(): array { $formatter = (new FormSubmissionFormatter($this->form, $this->data)) - ->useSignedUrlForFiles() - ->showHiddenFields() - ; + ->useSignedUrlForFiles() + ->showHiddenFields(); $formattedData = []; foreach ($formatter->getFieldsWithValue() as $field) { @@ -41,7 +37,7 @@ abstract class AbstractWebhookHandler 'submission' => $formattedData, ]; if ($this->form->is_pro && $this->form->editable_submissions) { - $data['edit_link'] = $this->form->share_url . '?submission_id=' . Hashids::encode($this->data['submission_id']); + $data['edit_link'] = $this->form->share_url.'?submission_id='.Hashids::encode($this->data['submission_id']); } return $data; @@ -51,8 +47,10 @@ abstract class AbstractWebhookHandler public function handle() { - if (!$this->shouldRun()) return; - + if (! $this->shouldRun()) { + return; + } + WebhookCall::create() // Add context on error, used to notify form owner ->meta([ diff --git a/app/Service/Forms/Webhooks/DiscordHandler.php b/app/Service/Forms/Webhooks/DiscordHandler.php index f7529f5..e13faba 100644 --- a/app/Service/Forms/Webhooks/DiscordHandler.php +++ b/app/Service/Forms/Webhooks/DiscordHandler.php @@ -3,12 +3,11 @@ namespace App\Service\Forms\Webhooks; use App\Service\Forms\FormSubmissionFormatter; -use Vinkla\Hashids\Facades\Hashids; use Illuminate\Support\Arr; +use Vinkla\Hashids\Facades\Hashids; class DiscordHandler extends AbstractWebhookHandler { - protected function getProviderName(): string { return 'Discord'; @@ -21,66 +20,66 @@ class DiscordHandler extends AbstractWebhookHandler protected function getWebhookData(): array { - $settings = (array) Arr::get((array)$this->form->notification_settings, 'discord', []); + $settings = (array) Arr::get((array) $this->form->notification_settings, 'discord', []); $externalLinks = []; - if(Arr::get($settings, 'link_open_form', true)){ - $externalLinks[] = '[**๐Ÿ”— Open Form**](' . $this->form->share_url . ')'; + if (Arr::get($settings, 'link_open_form', true)) { + $externalLinks[] = '[**๐Ÿ”— Open Form**]('.$this->form->share_url.')'; } - if(Arr::get($settings, 'link_edit_form', true)){ - $editFormURL = front_url('forms/' . $this->form->slug . '/show'); - $externalLinks[] = '[**โœ๏ธ Edit Form**](' . $editFormURL . ')'; + if (Arr::get($settings, 'link_edit_form', true)) { + $editFormURL = front_url('forms/'.$this->form->slug.'/show'); + $externalLinks[] = '[**โœ๏ธ Edit Form**]('.$editFormURL.')'; } if (Arr::get($settings, 'link_edit_submission', true) && $this->form->editable_submissions) { $submissionId = Hashids::encode($this->data['submission_id']); - $externalLinks[] = '[**โœ๏ธ ' . $this->form->editable_submissions_button_text . '**](' . $this->form->share_url . '?submission_id=' . $submissionId . ')'; + $externalLinks[] = '[**โœ๏ธ '.$this->form->editable_submissions_button_text.'**]('.$this->form->share_url.'?submission_id='.$submissionId.')'; } $color = hexdec(str_replace('#', '', $this->form->color)); $blocks = []; - if(Arr::get($settings, 'include_submission_data', true)){ - $submissionString = ""; + if (Arr::get($settings, 'include_submission_data', true)) { + $submissionString = ''; $formatter = (new FormSubmissionFormatter($this->form, $this->data))->outputStringsOnly(); foreach ($formatter->getFieldsWithValue() as $field) { - $tmpVal = is_array($field['value']) ? implode(",", $field['value']) : $field['value']; - $submissionString .= "**" . ucfirst($field['name']) . "**: " . $tmpVal . "\n"; + $tmpVal = is_array($field['value']) ? implode(',', $field['value']) : $field['value']; + $submissionString .= '**'.ucfirst($field['name']).'**: '.$tmpVal."\n"; } $blocks[] = [ - "type" => "rich", - "color" => $color, - "description" => $submissionString + 'type' => 'rich', + 'color' => $color, + 'description' => $submissionString, ]; } - if(Arr::get($settings, 'views_submissions_count', true)){ - $countString = '**๐Ÿ‘€ Views**: ' . (string)$this->form->views_count . " \n"; - $countString .= '**๐Ÿ–Š๏ธ Submissions**: ' . (string)$this->form->submissions_count; + if (Arr::get($settings, 'views_submissions_count', true)) { + $countString = '**๐Ÿ‘€ Views**: '.(string) $this->form->views_count." \n"; + $countString .= '**๐Ÿ–Š๏ธ Submissions**: '.(string) $this->form->submissions_count; $blocks[] = [ - "type" => "rich", - "color" => $color, - "description" => $countString + 'type' => 'rich', + 'color' => $color, + 'description' => $countString, ]; } - if(count($externalLinks) > 0){ + if (count($externalLinks) > 0) { $blocks[] = [ - "type" => "rich", - "color" => $color, - "description" => implode(' - ', $externalLinks) + 'type' => 'rich', + 'color' => $color, + 'description' => implode(' - ', $externalLinks), ]; } return [ - 'content' => 'New submission for your form **' . $this->form->title . '**', + 'content' => 'New submission for your form **'.$this->form->title.'**', 'tts' => false, 'username' => config('app.name'), 'avatar_url' => asset('img/logo.png'), - 'embeds' => $blocks + 'embeds' => $blocks, ]; } protected function shouldRun(): bool { - return !is_null($this->getWebhookUrl()) + return ! is_null($this->getWebhookUrl()) && str_contains($this->getWebhookUrl(), 'https://discord.com/api/webhooks') && $this->form->is_pro; } diff --git a/app/Service/Forms/Webhooks/SimpleWebhookHandler.php b/app/Service/Forms/Webhooks/SimpleWebhookHandler.php index 4d3add0..3b3ea53 100644 --- a/app/Service/Forms/Webhooks/SimpleWebhookHandler.php +++ b/app/Service/Forms/Webhooks/SimpleWebhookHandler.php @@ -2,9 +2,6 @@ namespace App\Service\Forms\Webhooks; -use App\Service\Forms\FormSubmissionFormatter; -use Illuminate\Support\Str; - class SimpleWebhookHandler extends AbstractWebhookHandler { protected function getProviderName(): string @@ -19,6 +16,6 @@ class SimpleWebhookHandler extends AbstractWebhookHandler protected function shouldRun(): bool { - return !is_null($this->getWebhookUrl()) && $this->form->is_pro; + return ! is_null($this->getWebhookUrl()) && $this->form->is_pro; } } diff --git a/app/Service/Forms/Webhooks/SlackHandler.php b/app/Service/Forms/Webhooks/SlackHandler.php index f237efa..229e496 100644 --- a/app/Service/Forms/Webhooks/SlackHandler.php +++ b/app/Service/Forms/Webhooks/SlackHandler.php @@ -3,12 +3,11 @@ namespace App\Service\Forms\Webhooks; use App\Service\Forms\FormSubmissionFormatter; -use Vinkla\Hashids\Facades\Hashids; use Illuminate\Support\Arr; +use Vinkla\Hashids\Facades\Hashids; class SlackHandler extends AbstractWebhookHandler { - protected function getProviderName(): string { return 'Slack'; @@ -21,18 +20,18 @@ class SlackHandler extends AbstractWebhookHandler protected function getWebhookData(): array { - $settings = (array) Arr::get((array)$this->form->notification_settings, 'slack', []); + $settings = (array) Arr::get((array) $this->form->notification_settings, 'slack', []); $externalLinks = []; - if(Arr::get($settings, 'link_open_form', true)){ - $externalLinks[] = '*<' . $this->form->share_url . '|๐Ÿ”— Open Form>*'; + if (Arr::get($settings, 'link_open_form', true)) { + $externalLinks[] = '*<'.$this->form->share_url.'|๐Ÿ”— Open Form>*'; } - if(Arr::get($settings, 'link_edit_form', true)){ - $editFormURL = front_url('forms/' . $this->form->slug . '/show'); - $externalLinks[] = '*<' . $editFormURL . '|โœ๏ธ Edit Form>*'; + if (Arr::get($settings, 'link_edit_form', true)) { + $editFormURL = front_url('forms/'.$this->form->slug.'/show'); + $externalLinks[] = '*<'.$editFormURL.'|โœ๏ธ Edit Form>*'; } if (Arr::get($settings, 'link_edit_submission', true) && $this->form->editable_submissions) { $submissionId = Hashids::encode($this->data['submission_id']); - $externalLinks[] = '*<' . $this->form->share_url . '?submission_id=' . $submissionId . '|โœ๏ธ ' . $this->form->editable_submissions_button_text . '>*'; + $externalLinks[] = '*<'.$this->form->share_url.'?submission_id='.$submissionId.'|โœ๏ธ '.$this->form->editable_submissions_button_text.'>*'; } $blocks = [ @@ -40,57 +39,57 @@ class SlackHandler extends AbstractWebhookHandler 'type' => 'section', 'text' => [ 'type' => 'mrkdwn', - 'text' => 'New submission for your form *' . $this->form->title . '*', - ] - ] + 'text' => 'New submission for your form *'.$this->form->title.'*', + ], + ], ]; - if(Arr::get($settings, 'include_submission_data', true)){ + if (Arr::get($settings, 'include_submission_data', true)) { $submissionString = ''; $formatter = (new FormSubmissionFormatter($this->form, $this->data))->outputStringsOnly(); foreach ($formatter->getFieldsWithValue() as $field) { $tmpVal = is_array($field['value']) ? implode(',', $field['value']) : $field['value']; - $submissionString .= '>*' . ucfirst($field['name']) . '*: ' . $tmpVal . " \n"; + $submissionString .= '>*'.ucfirst($field['name']).'*: '.$tmpVal." \n"; } $blocks[] = [ 'type' => 'section', 'text' => [ 'type' => 'mrkdwn', 'text' => $submissionString, - ] + ], ]; } - if(Arr::get($settings, 'views_submissions_count', true)){ - $countString = '*๐Ÿ‘€ Views*: ' . (string)$this->form->views_count . " \n"; - $countString .= '*๐Ÿ–Š๏ธ Submissions*: ' . (string)$this->form->submissions_count; + if (Arr::get($settings, 'views_submissions_count', true)) { + $countString = '*๐Ÿ‘€ Views*: '.(string) $this->form->views_count." \n"; + $countString .= '*๐Ÿ–Š๏ธ Submissions*: '.(string) $this->form->submissions_count; $blocks[] = [ 'type' => 'section', 'text' => [ 'type' => 'mrkdwn', 'text' => $countString, - ] + ], ]; } - if(count($externalLinks) > 0){ + if (count($externalLinks) > 0) { $blocks[] = [ 'type' => 'section', 'text' => [ 'type' => 'mrkdwn', 'text' => implode(' ', $externalLinks), - ] + ], ]; } return [ - 'blocks' => $blocks + 'blocks' => $blocks, ]; } protected function shouldRun(): bool { - return !is_null($this->getWebhookUrl()) + return ! is_null($this->getWebhookUrl()) && str_contains($this->getWebhookUrl(), 'https://hooks.slack.com/') && $this->form->is_pro; } diff --git a/app/Service/Forms/Webhooks/WebhookHandlerProvider.php b/app/Service/Forms/Webhooks/WebhookHandlerProvider.php index a271aa0..c4441d5 100644 --- a/app/Service/Forms/Webhooks/WebhookHandlerProvider.php +++ b/app/Service/Forms/Webhooks/WebhookHandlerProvider.php @@ -6,10 +6,13 @@ use App\Models\Forms\Form; class WebhookHandlerProvider { - const SLACK_PROVIDER = 'slack'; - const DISCORD_PROVIDER = 'discord'; - const SIMPLE_WEBHOOK_PROVIDER = 'webhook'; - const ZAPIER_PROVIDER = 'zapier'; + public const SLACK_PROVIDER = 'slack'; + + public const DISCORD_PROVIDER = 'discord'; + + public const SIMPLE_WEBHOOK_PROVIDER = 'webhook'; + + public const ZAPIER_PROVIDER = 'zapier'; public static function getProvider(Form $form, array $data, string $provider, ?string $webhookUrl = null) { @@ -24,6 +27,7 @@ class WebhookHandlerProvider if (is_null($webhookUrl)) { throw new \Exception('Zapier webhook url is required'); } + return new ZapierHandler($form, $data, $webhookUrl); default: throw new \Exception('Unknown webhook provider'); diff --git a/app/Service/Forms/Webhooks/ZapierHandler.php b/app/Service/Forms/Webhooks/ZapierHandler.php index e82c919..ab5ff17 100644 --- a/app/Service/Forms/Webhooks/ZapierHandler.php +++ b/app/Service/Forms/Webhooks/ZapierHandler.php @@ -22,6 +22,6 @@ class ZapierHandler extends AbstractWebhookHandler protected function shouldRun(): bool { - return !is_null($this->getWebhookUrl()); + return ! is_null($this->getWebhookUrl()); } } diff --git a/app/Service/HtmlPurifier/HTMLPurifier_URIScheme_notion.php b/app/Service/HtmlPurifier/HTMLPurifier_URIScheme_notion.php index 0272e5f..ea7f9c8 100644 --- a/app/Service/HtmlPurifier/HTMLPurifier_URIScheme_notion.php +++ b/app/Service/HtmlPurifier/HTMLPurifier_URIScheme_notion.php @@ -1,16 +1,11 @@ model = $model; + return $this; } public function setSystemMessage(string $systemMessage): self { $this->systemMessage = $systemMessage; + return $this; } public function useStreaming(): self { $this->useStreaming = true; + return $this; } public function expectsJson(): self { $this->expectsJson = true; + return $this; } public function doesNotExpectJson(): self { $this->expectsJson = false; + return $this; } public function completeChat(array $messages, int $maxTokens = 4096, float $temperature = 0.81, ?bool $exceptJson = null): self { - if (!is_null($exceptJson)) { + if (! is_null($exceptJson)) { $this->expectsJson = $exceptJson; } $this->computeChatCompletion($messages, $maxTokens, $temperature) @@ -89,18 +99,19 @@ class GptCompleter $payload = Str::of($this->result)->trim(); if ($payload->contains('```json')) { $payload = $payload->after('```json')->before('```'); - } else if ($payload->contains('```')) { + } elseif ($payload->contains('```')) { $payload = $payload->after('```')->before('```'); } $payload = $payload->toString(); $exception = null; try { - $newPayload = (new JsonFixer)->fix($payload); + $newPayload = (new JsonFixer())->fix($payload); + return json_decode($newPayload, true); } catch (\Aws\Exception\InvalidJsonException $e) { $exception = $e; - Log::warning("Invalid JSON, retrying:"); + Log::warning('Invalid JSON, retrying:'); Log::warning($payload); $this->queryCompletion(); } @@ -113,9 +124,10 @@ class GptCompleter $payload = Str::of($this->result)->trim(); if ($payload->contains('```html')) { $payload = $payload->after('```html')->before('```'); - } else if ($payload->contains('```')) { + } elseif ($payload->contains('```')) { $payload = $payload->after('```')->before('```'); } + return $payload->toString(); } @@ -134,7 +146,7 @@ class GptCompleter if (isset($this->systemMessage) && $messages[0]['role'] !== 'system') { $messages = array_merge([[ 'role' => 'system', - 'content' => $this->systemMessage + 'content' => $this->systemMessage, ]], $messages); } @@ -142,16 +154,17 @@ class GptCompleter 'model' => $this->model, 'messages' => $messages, 'max_tokens' => $maxTokens, - 'temperature' => $temperature + 'temperature' => $temperature, ]; if ($this->expectsJson) { $completionInput['response_format'] = [ - 'type' => 'json_object' + 'type' => 'json_object', ]; } $this->completionInput = $completionInput; + return $this; } @@ -162,7 +175,7 @@ class GptCompleter } try { - Log::debug("Open AI query: " . json_encode($this->completionInput)); + Log::debug('Open AI query: '.json_encode($this->completionInput)); $response = $this->openAi->chat()->create($this->completionInput); } catch (ErrorException $errorException) { // Retry once @@ -171,12 +184,13 @@ class GptCompleter } $this->tokenUsed += $response->usage->totalTokens; $this->result = $response->choices[0]->message->content; + return $this; } protected function queryStreamedCompletion(): self { - Log::debug("Open AI query: " . json_encode($this->completionInput)); + Log::debug('Open AI query: '.json_encode($this->completionInput)); $this->result = ''; $response = $this->openAi->chat()->createStreamed($this->completionInput); foreach ($response as $chunk) { diff --git a/app/Service/OpenAi/Utils/JsonFixer.php b/app/Service/OpenAi/Utils/JsonFixer.php index 80162a3..f4a66e9 100644 --- a/app/Service/OpenAi/Utils/JsonFixer.php +++ b/app/Service/OpenAi/Utils/JsonFixer.php @@ -53,13 +53,12 @@ class JsonFixer /** * Set/unset silent mode. * - * @param bool $silent - * + * @param bool $silent * @return $this */ public function silent($silent = true) { - $this->silent = (bool)$silent; + $this->silent = (bool) $silent; return $this; } @@ -67,8 +66,7 @@ class JsonFixer /** * Set missing value. * - * @param mixed $value - * + * @param mixed $value * @return $this */ public function missingValue($value) @@ -87,16 +85,15 @@ class JsonFixer /** * Fix the truncated JSON. * - * @param string $json The JSON string to fix. - * + * @param string $json The JSON string to fix. * @return string Fixed JSON. If failed with silent then original JSON. - * @throws InvalidJsonException When fixing fails. * + * @throws InvalidJsonException When fixing fails. */ public function fix($json) { $json = preg_replace('/(?trim($json); + [$head, $json, $tail] = $this->trim($json); if (empty($json) || $this->isValid($json)) { return $json; @@ -108,7 +105,7 @@ class JsonFixer $this->reset(); - return $head . $this->doFix($json) . $tail; + return $head.$this->doFix($json).$tail; } protected function trim($json) @@ -125,15 +122,15 @@ class JsonFixer protected function isValid($json) { - \json_decode($json,true,512,JSON_INVALID_UTF8_SUBSTITUTE); + \json_decode($json, true, 512, JSON_INVALID_UTF8_SUBSTITUTE); - return \JSON_ERROR_NONE === \json_last_error(); + return \json_last_error() === \JSON_ERROR_NONE; } protected function quickFix($json) { if (\strlen($json) === 1 && isset($this->pairs[$json])) { - return $json . $this->pairs[$json]; + return $json.$this->pairs[$json]; } if ($json[0] !== '"') { @@ -153,7 +150,7 @@ class JsonFixer protected function maybeLiteral($json) { - if (!\in_array($json[0], ['t', 'f', 'n'])) { + if (! \in_array($json[0], ['t', 'f', 'n'])) { return null; } @@ -170,14 +167,14 @@ class JsonFixer protected function doFix($json) { - list($index, $char) = [-1, '']; + [$index, $char] = [-1, '']; while (isset($json[++$index])) { - list($prev, $char) = [$char, $json[$index]]; + [$prev, $char] = [$char, $json[$index]]; $next = isset($json[$index + 1]) ? $json[$index + 1] : ''; - if (!\in_array($char, [' ', "\n", "\r"])) { + if (! \in_array($char, [' ', "\n", "\r"])) { $this->stack($prev, $char, $index, $next); } } @@ -212,7 +209,7 @@ class JsonFixer protected function popToken($token = null) { // Last one - if (null === $token) { + if ($token === null) { return \array_pop($this->stack); } @@ -228,7 +225,7 @@ class JsonFixer protected function maybeStr($prev, $char, $index) { if ($prev !== '\\' && $char === '"') { - $this->inStr = !$this->inStr; + $this->inStr = ! $this->inStr; } if ($this->inStr && $this->lastToken() !== '"') { @@ -267,7 +264,7 @@ class JsonFixer } \Log::debug('Broken json received: ', [ - 'json' => $json + 'json' => $json, ]); throw new InvalidJsonException( diff --git a/app/Service/OpenAi/Utils/PadsJson.php b/app/Service/OpenAi/Utils/PadsJson.php index 6d17c42..e4ede07 100644 --- a/app/Service/OpenAi/Utils/PadsJson.php +++ b/app/Service/OpenAi/Utils/PadsJson.php @@ -16,7 +16,7 @@ trait PadsJson { public function pad($tmpJson) { - if (!$this->inStr) { + if (! $this->inStr) { $tmpJson = \rtrim($tmpJson, ','); while ($this->lastToken() === ',') { $this->popToken(); @@ -37,11 +37,11 @@ trait PadsJson $match = \preg_match('/(tr?u?e?|fa?l?s?e?|nu?l?l?)$/', $tmpJson, $matches); - if (!$match || null === $literal = $this->maybeLiteral($matches[1])) { + if (! $match || null === $literal = $this->maybeLiteral($matches[1])) { return $tmpJson; } - return \substr($tmpJson, 0, 0 - \strlen($matches[1])) . $literal; + return \substr($tmpJson, 0, 0 - \strlen($matches[1])).$literal; } protected function padStack($tmpJson) @@ -57,7 +57,7 @@ trait PadsJson protected function padObject($tmpJson) { - if (!$this->objectNeedsPadding($tmpJson)) { + if (! $this->objectNeedsPadding($tmpJson)) { return $tmpJson; } @@ -71,7 +71,7 @@ trait PadsJson } $tmpJson = $this->padIf($tmpJson, ':'); - $tmpJson = $tmpJson . $this->missingValue; + $tmpJson = $tmpJson.$this->missingValue; if ($this->lastToken() === '"') { $this->popToken(); @@ -82,19 +82,19 @@ trait PadsJson protected function objectNeedsPadding($tmpJson) { - $last = \substr($tmpJson, -1); - $empty = $last === '{' && !$this->inStr; + $last = \substr($tmpJson, -1); + $empty = $last === '{' && ! $this->inStr; - return !$empty && $this->arrayPos < $this->objectPos; + return ! $empty && $this->arrayPos < $this->objectPos; } protected function padString($string) { - $last = \substr($string, -1); + $last = \substr($string, -1); $last2 = \substr($string, -2); if ($last2 === '\"' || $last !== '"') { - return $string . '"'; + return $string.'"'; } // @codeCoverageIgnoreStart @@ -105,7 +105,7 @@ trait PadsJson protected function padIf($string, $substr) { if (\substr($string, 0 - \strlen($substr)) !== $substr) { - return $string . $substr; + return $string.$substr; } return $string; diff --git a/app/Service/SeoMetaResolver.php b/app/Service/SeoMetaResolver.php index 7cbd84a..3f05d86 100644 --- a/app/Service/SeoMetaResolver.php +++ b/app/Service/SeoMetaResolver.php @@ -25,7 +25,7 @@ class SeoMetaResolver { private array $patternData = []; - const URL_PATTERNS = [ + public const URL_PATTERNS = [ 'welcome' => '/', 'form_show' => '/forms/{slug}', 'login' => '/login', @@ -43,7 +43,7 @@ class SeoMetaResolver /** * Metas for simple route (without needing to access DB) */ - const PATTERN_STATIC_META = [ + public const PATTERN_STATIC_META = [ 'login' => [ 'title' => 'Login', ], @@ -64,13 +64,13 @@ class SeoMetaResolver ], 'templates' => [ 'title' => 'Templates', - 'description' => 'Our collection of beautiful templates to create your own forms!' + 'description' => 'Our collection of beautiful templates to create your own forms!', ], ]; - const META_CACHE_DURATION = 60 * 60 * 12; // 12 hours + public const META_CACHE_DURATION = 60 * 60 * 12; // 12 hours - const META_CACHE_KEY_PREFIX = 'seo_meta_'; + public const META_CACHE_KEY_PREFIX = 'seo_meta_'; public function __construct(private Request $request) { @@ -78,12 +78,10 @@ class SeoMetaResolver /** * Returns the right metas for a given route, caches meta for 1 hour. - * - * @return array */ public function getMetas(): array { - $cacheKey = self::META_CACHE_KEY_PREFIX . urlencode($this->request->path()); + $cacheKey = self::META_CACHE_KEY_PREFIX.urlencode($this->request->path()); return Cache::remember($cacheKey, now()->addSeconds(self::META_CACHE_DURATION), function () { $pattern = $this->resolvePattern(); @@ -91,7 +89,7 @@ class SeoMetaResolver if ($this->hasPatternMetaGetter($pattern)) { // Custom function for pattern try { - return array_merge($this->getDefaultMeta(), $this->{'get' . Str::studly($pattern) . 'Meta'}()); + return array_merge($this->getDefaultMeta(), $this->{'get'.Str::studly($pattern).'Meta'}()); } catch (\Exception $e) { return $this->getDefaultMeta(); } @@ -122,7 +120,7 @@ class SeoMetaResolver foreach (self::URL_PATTERNS as $patternName => $patternData) { $path = rtrim($this->request->getPathInfo(), '/') ?: '/'; - $route = (new Route('GET', $patternData, fn() => ''))->bind($this->request); + $route = (new Route('GET', $patternData, fn () => ''))->bind($this->request); if (preg_match($route->getCompiled()->getRegex(), rawurldecode($path))) { $this->patternData = $route->parameters(); @@ -136,23 +134,23 @@ class SeoMetaResolver /** * Determine if a get mutator exists for a pattern. * - * @param string $key + * @param string $key * @return bool */ private function hasPatternMetaGetter($key) { - return method_exists($this, 'get' . Str::studly($key) . 'Meta'); + return method_exists($this, 'get'.Str::studly($key).'Meta'); } private function titleSuffix() { - return ' ยท ' . config('app.name'); + return ' ยท '.config('app.name'); } private function getDefaultMeta(): array { return [ - 'title' => 'Create beautiful forms for free' . $this->titleSuffix(), + 'title' => 'Create beautiful forms for free'.$this->titleSuffix(), 'description' => "Create beautiful forms for free. Unlimited fields, unlimited submissions. It's free and it takes less than 1 minute to create your first form.", 'image' => asset('/img/social-preview.jpg'), ]; @@ -166,21 +164,21 @@ class SeoMetaResolver if ($form->is_pro && $form->seo_meta->page_title) { $meta['title'] = $form->seo_meta->page_title; } else { - $meta['title'] = $form->title . $this->titleSuffix(); + $meta['title'] = $form->title.$this->titleSuffix(); } if ($form->is_pro && $form->seo_meta->page_description) { $meta['description'] = $form->seo_meta->page_description; - } else if ($form->description) { + } elseif ($form->description) { $meta['description'] = Str::of($form->description)->limit(160); } if ($form->is_pro && $form->seo_meta->page_thumbnail) { $meta['image'] = $form->seo_meta->page_thumbnail; - } else if ($form->cover_picture) { + } elseif ($form->cover_picture) { $meta['image'] = $form->cover_picture; } - + return $meta; } @@ -189,9 +187,9 @@ class SeoMetaResolver $template = Template::whereSlug($this->patternData['slug'])->firstOrFail(); return [ - 'title' => $template->name . $this->titleSuffix(), - 'description' => Str::of($template->short_description)->limit(140) . ' | Customize any template and create your own form in minutes.', - 'image' => $template->image_url + 'title' => $template->name.$this->titleSuffix(), + 'description' => Str::of($template->short_description)->limit(140).' | Customize any template and create your own form in minutes.', + 'image' => $template->image_url, ]; } diff --git a/app/Service/Storage/StorageFileNameParser.php b/app/Service/Storage/StorageFileNameParser.php index 0b1eddb..d418e23 100644 --- a/app/Service/Storage/StorageFileNameParser.php +++ b/app/Service/Storage/StorageFileNameParser.php @@ -13,7 +13,9 @@ use Illuminate\Support\Str; class StorageFileNameParser { public ?string $uuid = null; + public ?string $fileName = null; + public ?string $extension = null; public function __construct(string $fileName) @@ -24,15 +26,16 @@ class StorageFileNameParser /** * If we have parsed a file name and an extension, we keep the same and append uuid to avoid collisions * Otherwise we just return the uuid - * @return string */ public function getMovedFileName(): ?string { if ($this->fileName && $this->extension) { $fileName = substr($this->fileName, 0, 50).'_'.$this->uuid.'.'.$this->extension; $fileName = preg_replace('#\p{C}+#u', '', $fileName); // avoid CorruptedPathDetected exceptions + return mb_convert_encoding($fileName, 'UTF-8', 'UTF-8'); } + return $this->uuid; } @@ -40,16 +43,17 @@ class StorageFileNameParser { if (Str::isUuid($fileName)) { $this->uuid = $fileName; + return; } - if (!str_contains($fileName, '_')) { + if (! str_contains($fileName, '_')) { return; } $candidateString = substr($fileName, strrpos($fileName, '_') + 1); - if (!str_contains($candidateString, '.') - || !Str::isUuid(substr($candidateString, 0, strpos($candidateString, '.')))) { + if (! str_contains($candidateString, '.') + || ! Str::isUuid(substr($candidateString, 0, strpos($candidateString, '.')))) { return; } @@ -67,5 +71,4 @@ class StorageFileNameParser { return new self($fileName); } - } diff --git a/app/Service/WorkspaceHelper.php b/app/Service/WorkspaceHelper.php index b0e75ed..3fbe074 100644 --- a/app/Service/WorkspaceHelper.php +++ b/app/Service/WorkspaceHelper.php @@ -1,14 +1,11 @@ !empty(env('CADDY_SECRET')) && !empty(env('CADDY_AUTHORIZED_IPS', [])), + 'enabled' => ! empty(env('CADDY_SECRET')) && ! empty(env('CADDY_AUTHORIZED_IPS', [])), 'caddy_secret' => env('CADDY_SECRET'), - 'authorized_ips' => explode(',', env('CADDY_AUTHORIZED_IPS','')), + 'authorized_ips' => explode(',', env('CADDY_AUTHORIZED_IPS', '')), ]; diff --git a/config/excel.php b/config/excel.php index f43ff39..448b119 100644 --- a/config/excel.php +++ b/config/excel.php @@ -14,7 +14,7 @@ return [ | Here you can specify how big the chunk should be. | */ - 'chunk_size' => 1000, + 'chunk_size' => 1000, /* |-------------------------------------------------------------------------- @@ -41,14 +41,14 @@ return [ | Configure e.g. delimiter, enclosure and line ending for CSV exports. | */ - 'csv' => [ - 'delimiter' => ',', - 'enclosure' => '"', - 'line_ending' => PHP_EOL, - 'use_bom' => true, + 'csv' => [ + 'delimiter' => ',', + 'enclosure' => '"', + 'line_ending' => PHP_EOL, + 'use_bom' => true, 'include_separator_line' => false, - 'excel_compatibility' => false, - 'output_encoding' => '', + 'excel_compatibility' => false, + 'output_encoding' => '', ], /* @@ -59,20 +59,20 @@ return [ | Configure e.g. default title, creator, subject,... | */ - 'properties' => [ - 'creator' => '', + 'properties' => [ + 'creator' => '', 'lastModifiedBy' => '', - 'title' => '', - 'description' => '', - 'subject' => '', - 'keywords' => '', - 'category' => '', - 'manager' => '', - 'company' => '', + 'title' => '', + 'description' => '', + 'subject' => '', + 'keywords' => '', + 'category' => '', + 'manager' => '', + 'company' => '', ], ], - 'imports' => [ + 'imports' => [ /* |-------------------------------------------------------------------------- @@ -121,12 +121,12 @@ return [ | Configure e.g. delimiter, enclosure and line ending for CSV imports. | */ - 'csv' => [ - 'delimiter' => null, - 'enclosure' => '"', + 'csv' => [ + 'delimiter' => null, + 'enclosure' => '"', 'escape_character' => '\\', - 'contiguous' => false, - 'input_encoding' => 'UTF-8', + 'contiguous' => false, + 'input_encoding' => 'UTF-8', ], /* @@ -137,16 +137,16 @@ return [ | Configure e.g. default title, creator, subject,... | */ - 'properties' => [ - 'creator' => '', + 'properties' => [ + 'creator' => '', 'lastModifiedBy' => '', - 'title' => '', - 'description' => '', - 'subject' => '', - 'keywords' => '', - 'category' => '', - 'manager' => '', - 'company' => '', + 'title' => '', + 'description' => '', + 'subject' => '', + 'keywords' => '', + 'category' => '', + 'manager' => '', + 'company' => '', ], ], @@ -161,21 +161,21 @@ return [ | */ 'extension_detector' => [ - 'xlsx' => Excel::XLSX, - 'xlsm' => Excel::XLSX, - 'xltx' => Excel::XLSX, - 'xltm' => Excel::XLSX, - 'xls' => Excel::XLS, - 'xlt' => Excel::XLS, - 'ods' => Excel::ODS, - 'ots' => Excel::ODS, - 'slk' => Excel::SLK, - 'xml' => Excel::XML, + 'xlsx' => Excel::XLSX, + 'xlsm' => Excel::XLSX, + 'xltx' => Excel::XLSX, + 'xltm' => Excel::XLSX, + 'xls' => Excel::XLS, + 'xlt' => Excel::XLS, + 'ods' => Excel::ODS, + 'ots' => Excel::ODS, + 'slk' => Excel::SLK, + 'xml' => Excel::XML, 'gnumeric' => Excel::GNUMERIC, - 'htm' => Excel::HTML, - 'html' => Excel::HTML, - 'csv' => Excel::CSV, - 'tsv' => Excel::TSV, + 'htm' => Excel::HTML, + 'html' => Excel::HTML, + 'csv' => Excel::CSV, + 'tsv' => Excel::TSV, /* |-------------------------------------------------------------------------- @@ -186,7 +186,7 @@ return [ | Available options: Excel::MPDF | Excel::TCPDF | Excel::DOMPDF | */ - 'pdf' => Excel::DOMPDF, + 'pdf' => Excel::DOMPDF, ], /* @@ -227,7 +227,7 @@ return [ | Drivers: memory|illuminate|batch | */ - 'driver' => 'memory', + 'driver' => 'memory', /* |-------------------------------------------------------------------------- @@ -239,7 +239,7 @@ return [ | Here you can tweak the memory limit to your liking. | */ - 'batch' => [ + 'batch' => [ 'memory_limit' => 60000, ], @@ -277,7 +277,7 @@ return [ */ 'transactions' => [ 'handler' => 'db', - 'db' => [ + 'db' => [ 'connection' => null, ], ], @@ -293,7 +293,7 @@ return [ | storing reading or downloading. Here you can customize that path. | */ - 'local_path' => storage_path('framework/cache/laravel-excel'), + 'local_path' => storage_path('framework/cache/laravel-excel'), /* |-------------------------------------------------------------------------- @@ -309,8 +309,8 @@ return [ | in conjunction with queued imports and exports. | */ - 'remote_disk' => null, - 'remote_prefix' => null, + 'remote_disk' => null, + 'remote_prefix' => null, /* |-------------------------------------------------------------------------- diff --git a/config/links.php b/config/links.php index 775fe0f..504f56c 100644 --- a/config/links.php +++ b/config/links.php @@ -10,5 +10,5 @@ return [ 'twitter' => 'https://twitter.com/OpnForm', 'zapier_integration' => 'https://zapier.com/developer/public-invite/146950/58db583730cc46b821614468d94c35de/', 'book_onboarding' => 'https://zcal.co/i/YQVGEULQ', - 'feature_requests' => 'https://opnform.canny.io/feature-requests' + 'feature_requests' => 'https://opnform.canny.io/feature-requests', ]; diff --git a/config/model-stats.php b/config/model-stats.php index 024ca8d..3f4807b 100644 --- a/config/model-stats.php +++ b/config/model-stats.php @@ -43,7 +43,7 @@ return [ | This can be used to ensure a read-only connection, by using a custom connection with a read-only user. | */ - 'query_database_connection' => env('MODEL_STATS_DB_CONNECTION', env('DB_CONNECTION')), + 'query_database_connection' => env('MODEL_STATS_DB_CONNECTION', env('DB_CONNECTION')), /* |-------------------------------------------------------------------------- diff --git a/config/opnform.php b/config/opnform.php index 2bf9ff0..c47e97b 100644 --- a/config/opnform.php +++ b/config/opnform.php @@ -1,8 +1,8 @@ explode(",", env('ADMIN_EMAILS') ?? ''), - 'moderator_emails' => explode(",", env('MODERATOR_EMAILS') ?? ''), - 'template_editor_emails' => explode(",", env('TEMPLATE_EDITOR_EMAILS') ?? ''), - 'extra_pro_users_emails' => explode(",", env('EXTRA_PRO_USERS_EMAILS') ?? ''), + 'admin_emails' => explode(',', env('ADMIN_EMAILS') ?? ''), + 'moderator_emails' => explode(',', env('MODERATOR_EMAILS') ?? ''), + 'template_editor_emails' => explode(',', env('TEMPLATE_EDITOR_EMAILS') ?? ''), + 'extra_pro_users_emails' => explode(',', env('EXTRA_PRO_USERS_EMAILS') ?? ''), ]; diff --git a/config/pricing.php b/config/pricing.php index d96e405..965ce1f 100644 --- a/config/pricing.php +++ b/config/pricing.php @@ -8,8 +8,8 @@ return [ 'pricing' => [ 'monthly' => env('STRIPE_PROD_DEFAULT_PRICING_MONTHLY'), 'yearly' => env('STRIPE_PROD_DEFAULT_PRICING_YEARLY'), - ] - ] + ], + ], ], 'test' => [ @@ -18,8 +18,8 @@ return [ 'pricing' => [ 'monthly' => env('STRIPE_TEST_DEFAULT_PRICING_MONTHLY'), 'yearly' => env('STRIPE_TEST_DEFAULT_PRICING_YEARLY'), - ] - ] - ] + ], + ], + ], ]; diff --git a/config/purify.php b/config/purify.php index a02c845..3d8c009 100644 --- a/config/purify.php +++ b/config/purify.php @@ -149,7 +149,7 @@ return [ 'mailto' => true, 'tel' => true, 'notion' => true, - ] + ], ], diff --git a/config/sentry.php b/config/sentry.php index ea3e1a6..4f6f59d 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -50,7 +50,7 @@ return [ // @see: https://docs.sentry.io/platforms/php/configuration/options/#send-default-pii 'send_default_pii' => false, - 'traces_sample_rate' => (float)(env('SENTRY_TRACES_SAMPLE_RATE', 0.01)), + 'traces_sample_rate' => (float) (env('SENTRY_TRACES_SAMPLE_RATE', 0.01)), 'controllers_base_namespace' => env('SENTRY_CONTROLLERS_BASE_NAMESPACE', 'App\\Http\\Controllers'), diff --git a/config/services.php b/config/services.php index ad73b8b..d3e04a3 100644 --- a/config/services.php +++ b/config/services.php @@ -45,7 +45,7 @@ return [ ], 'notion' => [ - 'worker' => env('NOTION_WORKER', 'https://notion-forms-worker.notionforms.workers.dev/v1') + 'worker' => env('NOTION_WORKER', 'https://notion-forms-worker.notionforms.workers.dev/v1'), ], 'openai' => [ diff --git a/config/session.php b/config/session.php index 57c7ba0..5819290 100644 --- a/config/session.php +++ b/config/session.php @@ -1,7 +1,5 @@ env( - 'SESSION_COOKIE','OpnForm_session' + 'SESSION_COOKIE', + 'OpnForm_session' ), /* diff --git a/database/factories/FormFactory.php b/database/factories/FormFactory.php index dab01d3..55d8fcd 100644 --- a/database/factories/FormFactory.php +++ b/database/factories/FormFactory.php @@ -3,8 +3,8 @@ namespace Database\Factories; use App\Models\Forms\Form; -use App\Models\Workspace; use App\Models\User; +use App\Models\Workspace; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Str; @@ -97,8 +97,6 @@ class FormFactory extends Factory * - Adds id * - Adds placeholder, prefill, help * - Adds notion_name - * @param $properties - * @return array */ public static function formatProperties($properties): array { diff --git a/database/migrations/2021_05_19_140326_create_forms_table.php b/database/migrations/2021_05_19_140326_create_forms_table.php index 37892a1..f7be21e 100644 --- a/database/migrations/2021_05_19_140326_create_forms_table.php +++ b/database/migrations/2021_05_19_140326_create_forms_table.php @@ -19,7 +19,7 @@ class CreateFormsTable extends Migration Schema::create('forms', function (Blueprint $table) use ($driver) { $table->id(); - $table->foreignIdFor(\App\Models\Workspace::class,'workspace_id'); + $table->foreignIdFor(\App\Models\Workspace::class, 'workspace_id'); $table->string('title'); $table->string('slug'); $table->json('properties'); @@ -48,13 +48,13 @@ class CreateFormsTable extends Migration $table->boolean('transparent_background')->default(false); $table->timestamp('closes_at')->nullable(); $table->text('closed_text')->nullable(); - $table->string('notification_subject')->default("We saved your answers"); + $table->string('notification_subject')->default('We saved your answers'); $table->text('notification_body')->default(new Expression("('

Hello there ๐Ÿ‘‹
This is a confirmation that your submission was successfully saved.

')")); $table->boolean('notifications_include_submission')->default(true); $table->boolean('use_captcha')->default(false); $table->boolean('can_be_indexed')->default(true); $table->string('password')->nullable()->default(null); - $table->string('notification_sender')->default("OpenForm"); + $table->string('notification_sender')->default('OpenForm'); if ($driver === 'mysql') { $table->jsonb('tags')->default(new Expression('(JSON_ARRAY())')); } else { diff --git a/database/migrations/2021_05_24_234028_create_form_submissions_table.php b/database/migrations/2021_05_24_234028_create_form_submissions_table.php index b7e48af..03597ec 100644 --- a/database/migrations/2021_05_24_234028_create_form_submissions_table.php +++ b/database/migrations/2021_05_24_234028_create_form_submissions_table.php @@ -19,11 +19,11 @@ class CreateFormSubmissionsTable extends Migration Schema::create('form_submissions', function (Blueprint $table) use ($driver) { $table->id(); - $table->foreignIdFor(\App\Models\Forms\Form::class,'form_id'); + $table->foreignIdFor(\App\Models\Forms\Form::class, 'form_id'); if ($driver === 'mysql') { - $table->jsonb('data')->default(new Expression("(JSON_OBJECT())")); + $table->jsonb('data')->default(new Expression('(JSON_OBJECT())')); } else { - $table->jsonb('data')->default("{}"); + $table->jsonb('data')->default('{}'); } $table->timestamps(); }); diff --git a/database/migrations/2021_09_29_192133_create_form_zapier_webhooks_table.php b/database/migrations/2021_09_29_192133_create_form_zapier_webhooks_table.php index 0aa1fee..432f5cc 100644 --- a/database/migrations/2021_09_29_192133_create_form_zapier_webhooks_table.php +++ b/database/migrations/2021_09_29_192133_create_form_zapier_webhooks_table.php @@ -15,7 +15,7 @@ class CreateFormZapierWebhooksTable extends Migration { Schema::create('form_zapier_webhooks', function (Blueprint $table) { $table->id(); - $table->foreignIdFor(\App\Models\Forms\Form::class,'form_id'); + $table->foreignIdFor(\App\Models\Forms\Form::class, 'form_id'); $table->string('hook_url'); $table->softDeletes(); $table->timestamps(); diff --git a/database/migrations/2021_10_13_142022_create_users_workspaces_table.php b/database/migrations/2021_10_13_142022_create_users_workspaces_table.php index 6dd2776..455f651 100644 --- a/database/migrations/2021_10_13_142022_create_users_workspaces_table.php +++ b/database/migrations/2021_10_13_142022_create_users_workspaces_table.php @@ -37,8 +37,10 @@ class CreateUsersWorkspacesTable extends Migration echo '.'; // Make sure user wasn't deleted - if (!DB::table('users')->where('id', - $workspace->user_id)->exists()) { + if (! DB::table('users')->where( + 'id', + $workspace->user_id + )->exists()) { continue; } @@ -50,19 +52,19 @@ class CreateUsersWorkspacesTable extends Migration 'user_id' => $workspace->user_id, 'is_owner' => true, 'created_at' => $now, - 'updated_at' => $now + 'updated_at' => $now, ]); // Set form creator id - foreach (\App\Models\Forms\Form::withTrashed()->where('workspace_id',$workspace->id)->get() as $form) { - $form->update(['creator_id'=>$workspace->user_id]); + foreach (\App\Models\Forms\Form::withTrashed()->where('workspace_id', $workspace->id)->get() as $form) { + $form->update(['creator_id' => $workspace->user_id]); } } }); // Drop column Schema::table('workspaces', function (Blueprint $table) { - $table->dropColumn(['user_id','access_token']); + $table->dropColumn(['user_id', 'access_token']); }); Schema::table('user_workspace', function (Blueprint $table) { diff --git a/database/migrations/2022_05_02_092915_form_views.php b/database/migrations/2022_05_02_092915_form_views.php index 6be0952..9aa68c8 100644 --- a/database/migrations/2022_05_02_092915_form_views.php +++ b/database/migrations/2022_05_02_092915_form_views.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * @@ -15,7 +14,7 @@ return new class extends Migration { Schema::create('form_views', function (Blueprint $table) { $table->id(); - $table->foreignIdFor(\App\Models\Forms\Form::class,'form_id'); + $table->foreignIdFor(\App\Models\Forms\Form::class, 'form_id'); $table->timestamps(); }); } diff --git a/database/migrations/2022_05_10_144947_form_statistic.php b/database/migrations/2022_05_10_144947_form_statistic.php index 7cafb53..850e820 100644 --- a/database/migrations/2022_05_10_144947_form_statistic.php +++ b/database/migrations/2022_05_10_144947_form_statistic.php @@ -6,8 +6,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * @@ -19,11 +18,11 @@ return new class extends Migration Schema::create('form_statistics', function (Blueprint $table) use ($driver) { $table->id(); - $table->foreignIdFor(\App\Models\Forms\Form::class,'form_id'); + $table->foreignIdFor(\App\Models\Forms\Form::class, 'form_id'); if ($driver === 'mysql') { - $table->jsonb('data')->default(new Expression("(JSON_OBJECT())")); + $table->jsonb('data')->default(new Expression('(JSON_OBJECT())')); } else { - $table->jsonb('data')->default("{}"); + $table->jsonb('data')->default('{}'); } $table->date('date'); }); diff --git a/database/migrations/2022_08_18_133641_add_removed_properties_to_forms.php b/database/migrations/2022_08_18_133641_add_removed_properties_to_forms.php index 53568a9..b49dec5 100644 --- a/database/migrations/2022_08_18_133641_add_removed_properties_to_forms.php +++ b/database/migrations/2022_08_18_133641_add_removed_properties_to_forms.php @@ -6,8 +6,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * @@ -19,9 +18,9 @@ return new class extends Migration Schema::table('forms', function (Blueprint $table) use ($driver) { if ($driver === 'mysql') { - $table->jsonb('removed_properties')->default(new Expression("(JSON_ARRAY())")); + $table->jsonb('removed_properties')->default(new Expression('(JSON_ARRAY())')); } else { - $table->jsonb('removed_properties')->default("[]")->nullable(); + $table->jsonb('removed_properties')->default('[]')->nullable(); } }); } diff --git a/database/migrations/2022_09_06_044038_add_max_submissions_to_forms.php b/database/migrations/2022_09_06_044038_add_max_submissions_to_forms.php index 19d4acb..666c5da 100644 --- a/database/migrations/2022_09_06_044038_add_max_submissions_to_forms.php +++ b/database/migrations/2022_09_06_044038_add_max_submissions_to_forms.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2022_09_12_074636_remove_access_token_from_workspaces.php b/database/migrations/2022_09_12_074636_remove_access_token_from_workspaces.php index 67b3dbf..ea77e36 100644 --- a/database/migrations/2022_09_12_074636_remove_access_token_from_workspaces.php +++ b/database/migrations/2022_09_12_074636_remove_access_token_from_workspaces.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2022_09_16_110344_add_slack_webhook_url_to_forms.php b/database/migrations/2022_09_16_110344_add_slack_webhook_url_to_forms.php index 33df31c..63c37d5 100644 --- a/database/migrations/2022_09_16_110344_add_slack_webhook_url_to_forms.php +++ b/database/migrations/2022_09_16_110344_add_slack_webhook_url_to_forms.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2022_09_22_092205_create_templates_table.php b/database/migrations/2022_09_22_092205_create_templates_table.php index 0f7094f..695a32e 100644 --- a/database/migrations/2022_09_22_092205_create_templates_table.php +++ b/database/migrations/2022_09_22_092205_create_templates_table.php @@ -6,8 +6,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * @@ -25,7 +24,7 @@ return new class extends Migration $table->text('description'); $table->string('image_url'); if ($driver === 'mysql') { - $table->jsonb('structure')->default(new Expression("(JSON_OBJECT())")); + $table->jsonb('structure')->default(new Expression('(JSON_OBJECT())')); } else { $table->jsonb('structure')->default('{}'); } diff --git a/database/migrations/2022_09_26_084721_add_questions_to_templates.php b/database/migrations/2022_09_26_084721_add_questions_to_templates.php index 1fd0c50..83b5e3c 100644 --- a/database/migrations/2022_09_26_084721_add_questions_to_templates.php +++ b/database/migrations/2022_09_26_084721_add_questions_to_templates.php @@ -6,8 +6,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * @@ -16,10 +15,10 @@ return new class extends Migration public function up() { $driver = DB::getDriverName(); - + Schema::table('templates', function (Blueprint $table) use ($driver) { if ($driver === 'mysql') { - $table->jsonb('questions')->default(new Expression("(JSON_ARRAY())")); + $table->jsonb('questions')->default(new Expression('(JSON_ARRAY())')); } else { $table->jsonb('questions')->default('[]'); } diff --git a/database/migrations/2022_10_07_122038_add_visibility_to_forms.php b/database/migrations/2022_10_07_122038_add_visibility_to_forms.php index acea5b7..8008479 100644 --- a/database/migrations/2022_10_07_122038_add_visibility_to_forms.php +++ b/database/migrations/2022_10_07_122038_add_visibility_to_forms.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2022_12_27_114803_add_editable_submissions_to_forms.php b/database/migrations/2022_12_27_114803_add_editable_submissions_to_forms.php index 4e88969..f032679 100644 --- a/database/migrations/2022_12_27_114803_add_editable_submissions_to_forms.php +++ b/database/migrations/2022_12_27_114803_add_editable_submissions_to_forms.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2023_01_28_142618_add_discord_url.php b/database/migrations/2023_01_28_142618_add_discord_url.php index dd403f2..79b0f16 100644 --- a/database/migrations/2023_01_28_142618_add_discord_url.php +++ b/database/migrations/2023_01_28_142618_add_discord_url.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2023_03_06_033440_change_max_submissions_reached_text_to_text.php b/database/migrations/2023_03_06_033440_change_max_submissions_reached_text_to_text.php index eb15040..c739396 100644 --- a/database/migrations/2023_03_06_033440_change_max_submissions_reached_text_to_text.php +++ b/database/migrations/2023_03_06_033440_change_max_submissions_reached_text_to_text.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2023_03_13_094806_add_editable_submissions_button_text_to_forms.php b/database/migrations/2023_03_13_094806_add_editable_submissions_button_text_to_forms.php index d412da9..5aca5b6 100644 --- a/database/migrations/2023_03_13_094806_add_editable_submissions_button_text_to_forms.php +++ b/database/migrations/2023_03_13_094806_add_editable_submissions_button_text_to_forms.php @@ -5,8 +5,7 @@ use Illuminate\Database\Query\Expression; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2023_03_14_094623_change_templates_image_url_to_nullable.php b/database/migrations/2023_03_14_094623_change_templates_image_url_to_nullable.php index 8dbe017..450cdd9 100644 --- a/database/migrations/2023_03_14_094623_change_templates_image_url_to_nullable.php +++ b/database/migrations/2023_03_14_094623_change_templates_image_url_to_nullable.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2023_03_27_153317_create_ai_form_completions_table.php b/database/migrations/2023_03_27_153317_create_ai_form_completions_table.php index 88de1d3..383c8d5 100644 --- a/database/migrations/2023_03_27_153317_create_ai_form_completions_table.php +++ b/database/migrations/2023_03_27_153317_create_ai_form_completions_table.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2023_03_27_173507_create_jobs_table.php b/database/migrations/2023_03_27_173507_create_jobs_table.php index a786a89..67b0dda 100644 --- a/database/migrations/2023_03_27_173507_create_jobs_table.php +++ b/database/migrations/2023_03_27_173507_create_jobs_table.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2023_04_04_093956_add_confetti_on_submission_to_forms.php b/database/migrations/2023_04_04_093956_add_confetti_on_submission_to_forms.php index 706b597..dd200e4 100644 --- a/database/migrations/2023_04_04_093956_add_confetti_on_submission_to_forms.php +++ b/database/migrations/2023_04_04_093956_add_confetti_on_submission_to_forms.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2023_07_20_073728_add_seo_meta_to_forms.php b/database/migrations/2023_07_20_073728_add_seo_meta_to_forms.php index 01fa247..98e7443 100644 --- a/database/migrations/2023_07_20_073728_add_seo_meta_to_forms.php +++ b/database/migrations/2023_07_20_073728_add_seo_meta_to_forms.php @@ -6,8 +6,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * @@ -16,12 +15,12 @@ return new class extends Migration public function up() { $driver = DB::getDriverName(); - + Schema::table('forms', function (Blueprint $table) use ($driver) { if ($driver === 'mysql') { - $table->json('seo_meta')->default(new Expression("(JSON_OBJECT())")); + $table->json('seo_meta')->default(new Expression('(JSON_OBJECT())')); } else { - $table->json('seo_meta')->default("{}"); + $table->json('seo_meta')->default('{}'); } }); } diff --git a/database/migrations/2023_08_23_100710_add_notification_settings_to_forms.php b/database/migrations/2023_08_23_100710_add_notification_settings_to_forms.php index 37f3202..c8c7769 100644 --- a/database/migrations/2023_08_23_100710_add_notification_settings_to_forms.php +++ b/database/migrations/2023_08_23_100710_add_notification_settings_to_forms.php @@ -6,8 +6,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * @@ -19,7 +18,7 @@ return new class extends Migration Schema::table('forms', function (Blueprint $table) use ($driver) { if ($driver === 'mysql') { - $table->json('notification_settings')->default(new Expression("(JSON_OBJECT())"))->nullable(true); + $table->json('notification_settings')->default(new Expression('(JSON_OBJECT())'))->nullable(true); } else { $table->json('notification_settings')->default('{}')->nullable(true); } diff --git a/database/migrations/2023_09_01_052507_add_fields_to_templates.php b/database/migrations/2023_09_01_052507_add_fields_to_templates.php index a4b8e74..3e25433 100644 --- a/database/migrations/2023_09_01_052507_add_fields_to_templates.php +++ b/database/migrations/2023_09_01_052507_add_fields_to_templates.php @@ -6,8 +6,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * @@ -21,13 +20,13 @@ return new class extends Migration $table->boolean('publicly_listed')->default(false); if ($driver === 'mysql') { - $table->jsonb('industries')->default(new Expression("(JSON_ARRAY())")); + $table->jsonb('industries')->default(new Expression('(JSON_ARRAY())')); } else { $table->jsonb('industries')->default('[]'); } if ($driver === 'mysql') { - $table->jsonb('types')->default(new Expression("(JSON_ARRAY())")); + $table->jsonb('types')->default(new Expression('(JSON_ARRAY())')); } else { $table->jsonb('types')->default('[]'); } @@ -35,12 +34,12 @@ return new class extends Migration $table->string('short_description')->nullable(); if ($driver === 'mysql') { - $table->jsonb('related_templates')->default(new Expression("(JSON_ARRAY())")); + $table->jsonb('related_templates')->default(new Expression('(JSON_ARRAY())')); } else { $table->jsonb('related_templates')->default('[]'); } - - $table->string('image_url',500)->nullable()->change(); + + $table->string('image_url', 500)->nullable()->change(); }); } diff --git a/database/migrations/2023_09_21_092812_add_creator_id_to_templates.php b/database/migrations/2023_09_21_092812_add_creator_id_to_templates.php index b35a1b1..a96a58a 100644 --- a/database/migrations/2023_09_21_092812_add_creator_id_to_templates.php +++ b/database/migrations/2023_09_21_092812_add_creator_id_to_templates.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * @@ -14,7 +13,7 @@ return new class extends Migration public function up() { Schema::table('templates', function (Blueprint $table) { - $table->foreignIdFor(\App\Models\User::class,'creator_id')->nullable(); + $table->foreignIdFor(\App\Models\User::class, 'creator_id')->nullable(); }); } diff --git a/database/migrations/2023_10_10_140600_add_auto_save_to_forms.php b/database/migrations/2023_10_10_140600_add_auto_save_to_forms.php index fd9f817..3c9ff79 100644 --- a/database/migrations/2023_10_10_140600_add_auto_save_to_forms.php +++ b/database/migrations/2023_10_10_140600_add_auto_save_to_forms.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2023_10_13_080104_change_type_of_form_prompt_in_ai_form_completions.php b/database/migrations/2023_10_13_080104_change_type_of_form_prompt_in_ai_form_completions.php index 5d84765..4ce084d 100644 --- a/database/migrations/2023_10_13_080104_change_type_of_form_prompt_in_ai_form_completions.php +++ b/database/migrations/2023_10_13_080104_change_type_of_form_prompt_in_ai_form_completions.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2023_10_30_133259_create_licenses_table.php b/database/migrations/2023_10_30_133259_create_licenses_table.php index 034cde5..7f0979d 100644 --- a/database/migrations/2023_10_30_133259_create_licenses_table.php +++ b/database/migrations/2023_10_30_133259_create_licenses_table.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/database/migrations/2023_11_28_104644_add_custom_domains_to_workspaces_table.php b/database/migrations/2023_11_28_104644_add_custom_domains_to_workspaces_table.php index 166d075..3d97280 100644 --- a/database/migrations/2023_11_28_104644_add_custom_domains_to_workspaces_table.php +++ b/database/migrations/2023_11_28_104644_add_custom_domains_to_workspaces_table.php @@ -5,7 +5,7 @@ use Illuminate\Database\Query\Expression; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration { +return new class () extends Migration { /** * Run the migrations. * @@ -14,9 +14,9 @@ return new class extends Migration { public function up() { $driver = DB::getDriverName(); - Schema::table('workspaces', function (Blueprint $table) use ($driver){ + Schema::table('workspaces', function (Blueprint $table) use ($driver) { if ($driver === 'mysql') { - $table->json('custom_domains')->default(new Expression("(JSON_OBJECT())"))->nullable(true); + $table->json('custom_domains')->default(new Expression('(JSON_OBJECT())'))->nullable(true); } else { $table->json('custom_domains')->default('{}')->nullable(true); } diff --git a/database/migrations/2023_11_28_161121_add_custom_domain_to_forms_table.php b/database/migrations/2023_11_28_161121_add_custom_domain_to_forms_table.php index 456a758..90b1759 100644 --- a/database/migrations/2023_11_28_161121_add_custom_domain_to_forms_table.php +++ b/database/migrations/2023_11_28_161121_add_custom_domain_to_forms_table.php @@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * diff --git a/pint.json b/pint.json new file mode 100644 index 0000000..684f282 --- /dev/null +++ b/pint.json @@ -0,0 +1,3 @@ +{ + "preset": "psr12" +} diff --git a/resources/lang/de-DE/passwords.php b/resources/lang/de-DE/passwords.php index b9f3829..abdf90d 100644 --- a/resources/lang/de-DE/passwords.php +++ b/resources/lang/de-DE/passwords.php @@ -17,6 +17,6 @@ return [ 'sent' => 'Wir haben dir einen Link zum Zurรผcksetzen deines Passwort per Email zugeschickt!', 'throttled' => 'Bitte warte kurz bevor du es erneut versuchst.', 'token' => 'Der Passwort Reset Token ist invalide.', - 'user' => "Ein Nutzer mit dieser Email-Adresse konnte nicht gefunden werden.", + 'user' => 'Ein Nutzer mit dieser Email-Adresse konnte nicht gefunden werden.', ]; diff --git a/resources/lang/de-DE/validation.php b/resources/lang/de-DE/validation.php index 77a0449..6fbb4d6 100644 --- a/resources/lang/de-DE/validation.php +++ b/resources/lang/de-DE/validation.php @@ -141,37 +141,37 @@ return [ | */ - 'attributes' => [ - 'name' => 'Name', - 'username' => 'Nutzername', - 'email' => 'E-Mail Adresse', - 'first_name' => 'Vorname', - 'last_name' => 'Nachname', - 'password' => 'Passwort', + 'attributes' => [ + 'name' => 'Name', + 'username' => 'Nutzername', + 'email' => 'E-Mail Adresse', + 'first_name' => 'Vorname', + 'last_name' => 'Nachname', + 'password' => 'Passwort', 'password_confirmation' => 'Passwort bestรคtigen', - 'city' => 'Stadt', - 'country' => 'Land', - 'address' => 'Adresse', - 'phone' => 'Telefon', - 'mobile' => 'Handynummer', - 'age' => 'Alter', - 'sex' => 'Geschlecht', - 'gender' => 'Geschlecht', - 'year' => 'Jahr', - 'month' => 'Monat', - 'day' => 'Tag', - 'hour' => 'Stunde', - 'minute' => 'Minute', - 'second' => 'Sekunde', - 'title' => 'Titel', - 'content' => 'Inhalt', - 'body' => 'Inhalt', - 'description' => 'Beschreibung', - 'excerpt' => 'Ausschnitt', - 'date' => 'Datum', - 'time' => 'Zeit', - 'subject' => 'Betreff', - 'message' => 'Nachricht', + 'city' => 'Stadt', + 'country' => 'Land', + 'address' => 'Adresse', + 'phone' => 'Telefon', + 'mobile' => 'Handynummer', + 'age' => 'Alter', + 'sex' => 'Geschlecht', + 'gender' => 'Geschlecht', + 'year' => 'Jahr', + 'month' => 'Monat', + 'day' => 'Tag', + 'hour' => 'Stunde', + 'minute' => 'Minute', + 'second' => 'Sekunde', + 'title' => 'Titel', + 'content' => 'Inhalt', + 'body' => 'Inhalt', + 'description' => 'Beschreibung', + 'excerpt' => 'Ausschnitt', + 'date' => 'Datum', + 'time' => 'Zeit', + 'subject' => 'Betreff', + 'message' => 'Nachricht', ], ]; diff --git a/resources/lang/es/auth.php b/resources/lang/es/auth.php index 6d03049..5030867 100755 --- a/resources/lang/es/auth.php +++ b/resources/lang/es/auth.php @@ -13,7 +13,7 @@ return [ | */ - 'failed' => 'Estas credenciales no coinciden con nuestros registros.', + 'failed' => 'Estas credenciales no coinciden con nuestros registros.', 'throttle' => 'Demasiados intentos de acceso. Por favor intente nuevamente en :seconds segundos.', ]; diff --git a/resources/lang/es/pagination.php b/resources/lang/es/pagination.php index 325916d..f8f044e 100755 --- a/resources/lang/es/pagination.php +++ b/resources/lang/es/pagination.php @@ -14,6 +14,6 @@ return [ */ 'previous' => '« Anterior', - 'next' => 'Siguiente »', + 'next' => 'Siguiente »', ]; diff --git a/resources/lang/es/passwords.php b/resources/lang/es/passwords.php index f4639e3..802050d 100755 --- a/resources/lang/es/passwords.php +++ b/resources/lang/es/passwords.php @@ -14,9 +14,9 @@ return [ */ 'password' => 'Las contraseรฑas deben coincidir y contener al menos 6 caracteres', - 'reset' => 'ยกTu contraseรฑa ha sido restablecida!', - 'sent' => 'ยกTe hemos enviado por correo el enlace para restablecer tu contraseรฑa!', - 'token' => 'El token de recuperaciรณn de contraseรฑa es invรกlido.', - 'user' => 'No podemos encontrar ningรบn usuario con ese correo electrรณnico.', + 'reset' => 'ยกTu contraseรฑa ha sido restablecida!', + 'sent' => 'ยกTe hemos enviado por correo el enlace para restablecer tu contraseรฑa!', + 'token' => 'El token de recuperaciรณn de contraseรฑa es invรกlido.', + 'user' => 'No podemos encontrar ningรบn usuario con ese correo electrรณnico.', ]; diff --git a/resources/lang/es/validation.php b/resources/lang/es/validation.php index 43aae7a..81f4324 100755 --- a/resources/lang/es/validation.php +++ b/resources/lang/es/validation.php @@ -13,80 +13,80 @@ return [ | */ - 'accepted' => ':attribute debe ser aceptado.', - 'active_url' => ':attribute no es una URL vรกlida.', - 'after' => ':attribute debe ser una fecha posterior a :date.', - 'after_or_equal' => ':attribute debe ser una fecha posterior o igual a :date.', - 'alpha' => ':attribute sรณlo debe contener letras.', - 'alpha_dash' => ':attribute sรณlo debe contener letras, nรบmeros y guiones.', - 'alpha_num' => ':attribute sรณlo debe contener letras y nรบmeros.', - 'array' => ':attribute debe ser un conjunto.', - 'before' => ':attribute debe ser una fecha anterior a :date.', - 'before_or_equal' => ':attribute debe ser una fecha anterior o igual a :date.', - 'between' => [ + 'accepted' => ':attribute debe ser aceptado.', + 'active_url' => ':attribute no es una URL vรกlida.', + 'after' => ':attribute debe ser una fecha posterior a :date.', + 'after_or_equal' => ':attribute debe ser una fecha posterior o igual a :date.', + 'alpha' => ':attribute sรณlo debe contener letras.', + 'alpha_dash' => ':attribute sรณlo debe contener letras, nรบmeros y guiones.', + 'alpha_num' => ':attribute sรณlo debe contener letras y nรบmeros.', + 'array' => ':attribute debe ser un conjunto.', + 'before' => ':attribute debe ser una fecha anterior a :date.', + 'before_or_equal' => ':attribute debe ser una fecha anterior o igual a :date.', + 'between' => [ 'numeric' => ':attribute tiene que estar entre :min - :max.', - 'file' => ':attribute debe pesar entre :min - :max kilobytes.', - 'string' => ':attribute tiene que tener entre :min - :max caracteres.', - 'array' => ':attribute tiene que tener entre :min - :max รญtems.', + 'file' => ':attribute debe pesar entre :min - :max kilobytes.', + 'string' => ':attribute tiene que tener entre :min - :max caracteres.', + 'array' => ':attribute tiene que tener entre :min - :max รญtems.', ], - 'boolean' => 'El campo :attribute debe tener un valor verdadero o falso.', - 'confirmed' => 'La confirmaciรณn de :attribute no coincide.', - 'date' => ':attribute no es una fecha vรกlida.', - 'date_format' => ':attribute no corresponde al formato :format.', - 'different' => ':attribute y :other deben ser diferentes.', - 'digits' => ':attribute debe tener :digits dรญgitos.', - 'digits_between' => ':attribute debe tener entre :min y :max dรญgitos.', - 'dimensions' => 'Las dimensiones de la imagen :attribute no son vรกlidas.', - 'distinct' => 'El campo :attribute contiene un valor duplicado.', - 'email' => ':attribute no es un correo vรกlido', - 'exists' => ':attribute es invรกlido.', - 'file' => 'El campo :attribute debe ser un archivo.', - 'filled' => 'El campo :attribute es obligatorio.', - 'image' => ':attribute debe ser una imagen.', - 'in' => ':attribute es invรกlido.', - 'in_array' => 'El campo :attribute no existe en :other.', - 'integer' => ':attribute debe ser un nรบmero entero.', - 'ip' => ':attribute debe ser una direcciรณn IP vรกlida.', - 'ipv4' => ':attribute debe ser un direcciรณn IPv4 vรกlida', - 'ipv6' => ':attribute debe ser un direcciรณn IPv6 vรกlida.', - 'json' => 'El campo :attribute debe tener una cadena JSON vรกlida.', - 'max' => [ + 'boolean' => 'El campo :attribute debe tener un valor verdadero o falso.', + 'confirmed' => 'La confirmaciรณn de :attribute no coincide.', + 'date' => ':attribute no es una fecha vรกlida.', + 'date_format' => ':attribute no corresponde al formato :format.', + 'different' => ':attribute y :other deben ser diferentes.', + 'digits' => ':attribute debe tener :digits dรญgitos.', + 'digits_between' => ':attribute debe tener entre :min y :max dรญgitos.', + 'dimensions' => 'Las dimensiones de la imagen :attribute no son vรกlidas.', + 'distinct' => 'El campo :attribute contiene un valor duplicado.', + 'email' => ':attribute no es un correo vรกlido', + 'exists' => ':attribute es invรกlido.', + 'file' => 'El campo :attribute debe ser un archivo.', + 'filled' => 'El campo :attribute es obligatorio.', + 'image' => ':attribute debe ser una imagen.', + 'in' => ':attribute es invรกlido.', + 'in_array' => 'El campo :attribute no existe en :other.', + 'integer' => ':attribute debe ser un nรบmero entero.', + 'ip' => ':attribute debe ser una direcciรณn IP vรกlida.', + 'ipv4' => ':attribute debe ser un direcciรณn IPv4 vรกlida', + 'ipv6' => ':attribute debe ser un direcciรณn IPv6 vรกlida.', + 'json' => 'El campo :attribute debe tener una cadena JSON vรกlida.', + 'max' => [ 'numeric' => ':attribute no debe ser mayor a :max.', - 'file' => ':attribute no debe ser mayor que :max kilobytes.', - 'string' => ':attribute no debe ser mayor que :max caracteres.', - 'array' => ':attribute no debe tener mรกs de :max elementos.', + 'file' => ':attribute no debe ser mayor que :max kilobytes.', + 'string' => ':attribute no debe ser mayor que :max caracteres.', + 'array' => ':attribute no debe tener mรกs de :max elementos.', ], - 'mimes' => ':attribute debe ser un archivo con formato: :values.', - 'mimetypes' => ':attribute debe ser un archivo con formato: :values.', - 'min' => [ + 'mimes' => ':attribute debe ser un archivo con formato: :values.', + 'mimetypes' => ':attribute debe ser un archivo con formato: :values.', + 'min' => [ 'numeric' => 'El tamaรฑo de :attribute debe ser de al menos :min.', - 'file' => 'El tamaรฑo de :attribute debe ser de al menos :min kilobytes.', - 'string' => ':attribute debe contener al menos :min caracteres.', - 'array' => ':attribute debe tener al menos :min elementos.', + 'file' => 'El tamaรฑo de :attribute debe ser de al menos :min kilobytes.', + 'string' => ':attribute debe contener al menos :min caracteres.', + 'array' => ':attribute debe tener al menos :min elementos.', ], - 'not_in' => ':attribute es invรกlido.', - 'numeric' => ':attribute debe ser numรฉrico.', - 'present' => 'El campo :attribute debe estar presente.', - 'regex' => 'El formato de :attribute es invรกlido.', - 'required' => 'El campo :attribute es obligatorio.', - 'required_if' => 'El campo :attribute es obligatorio cuando :other es :value.', - 'required_unless' => 'El campo :attribute es obligatorio a menos que :other estรฉ en :values.', - 'required_with' => 'El campo :attribute es obligatorio cuando :values estรก presente.', - 'required_with_all' => 'El campo :attribute es obligatorio cuando :values estรก presente.', - 'required_without' => 'El campo :attribute es obligatorio cuando :values no estรก presente.', + 'not_in' => ':attribute es invรกlido.', + 'numeric' => ':attribute debe ser numรฉrico.', + 'present' => 'El campo :attribute debe estar presente.', + 'regex' => 'El formato de :attribute es invรกlido.', + 'required' => 'El campo :attribute es obligatorio.', + 'required_if' => 'El campo :attribute es obligatorio cuando :other es :value.', + 'required_unless' => 'El campo :attribute es obligatorio a menos que :other estรฉ en :values.', + 'required_with' => 'El campo :attribute es obligatorio cuando :values estรก presente.', + 'required_with_all' => 'El campo :attribute es obligatorio cuando :values estรก presente.', + 'required_without' => 'El campo :attribute es obligatorio cuando :values no estรก presente.', 'required_without_all' => 'El campo :attribute es obligatorio cuando ninguno de :values estรฉn presentes.', - 'same' => ':attribute y :other deben coincidir.', - 'size' => [ + 'same' => ':attribute y :other deben coincidir.', + 'size' => [ 'numeric' => 'El tamaรฑo de :attribute debe ser :size.', - 'file' => 'El tamaรฑo de :attribute debe ser :size kilobytes.', - 'string' => ':attribute debe contener :size caracteres.', - 'array' => ':attribute debe contener :size elementos.', + 'file' => 'El tamaรฑo de :attribute debe ser :size kilobytes.', + 'string' => ':attribute debe contener :size caracteres.', + 'array' => ':attribute debe contener :size elementos.', ], - 'string' => 'El campo :attribute debe ser una cadena de caracteres.', - 'timezone' => 'El :attribute debe ser una zona vรกlida.', - 'unique' => ':attribute ya ha sido registrado.', - 'uploaded' => 'Subir :attribute ha fallado.', - 'url' => 'El formato :attribute es invรกlido.', + 'string' => 'El campo :attribute debe ser una cadena de caracteres.', + 'timezone' => 'El :attribute debe ser una zona vรกlida.', + 'unique' => ':attribute ya ha sido registrado.', + 'uploaded' => 'Subir :attribute ha fallado.', + 'url' => 'El formato :attribute es invรกlido.', /* |-------------------------------------------------------------------------- @@ -99,7 +99,7 @@ return [ | */ - 'custom' => [ + 'custom' => [ 'password' => [ 'min' => 'La :attribute debe contener mรกs de :min caracteres', ], @@ -119,37 +119,37 @@ return [ | */ - 'attributes' => [ - 'name' => 'nombre', - 'username' => 'usuario', - 'email' => 'correo electrรณnico', - 'first_name' => 'nombre', - 'last_name' => 'apellido', - 'password' => 'contraseรฑa', + 'attributes' => [ + 'name' => 'nombre', + 'username' => 'usuario', + 'email' => 'correo electrรณnico', + 'first_name' => 'nombre', + 'last_name' => 'apellido', + 'password' => 'contraseรฑa', 'password_confirmation' => 'confirmaciรณn de la contraseรฑa', - 'city' => 'ciudad', - 'country' => 'paรญs', - 'address' => 'direcciรณn', - 'phone' => 'telรฉfono', - 'mobile' => 'mรณvil', - 'age' => 'edad', - 'sex' => 'sexo', - 'gender' => 'gรฉnero', - 'year' => 'aรฑo', - 'month' => 'mes', - 'day' => 'dรญa', - 'hour' => 'hora', - 'minute' => 'minuto', - 'second' => 'segundo', - 'title' => 'tรญtulo', - 'content' => 'contenido', - 'body' => 'contenido', - 'description' => 'descripciรณn', - 'excerpt' => 'extracto', - 'date' => 'fecha', - 'time' => 'hora', - 'subject' => 'asunto', - 'message' => 'mensaje', + 'city' => 'ciudad', + 'country' => 'paรญs', + 'address' => 'direcciรณn', + 'phone' => 'telรฉfono', + 'mobile' => 'mรณvil', + 'age' => 'edad', + 'sex' => 'sexo', + 'gender' => 'gรฉnero', + 'year' => 'aรฑo', + 'month' => 'mes', + 'day' => 'dรญa', + 'hour' => 'hora', + 'minute' => 'minuto', + 'second' => 'segundo', + 'title' => 'tรญtulo', + 'content' => 'contenido', + 'body' => 'contenido', + 'description' => 'descripciรณn', + 'excerpt' => 'extracto', + 'date' => 'fecha', + 'time' => 'hora', + 'subject' => 'asunto', + 'message' => 'mensaje', ], ]; diff --git a/resources/lang/nb-NO/auth.php b/resources/lang/nb-NO/auth.php index bfb5c76..1b07cca 100644 --- a/resources/lang/nb-NO/auth.php +++ b/resources/lang/nb-NO/auth.php @@ -15,6 +15,5 @@ return [ 'failed' => 'Brukernavn og passord stemmer ikke.', 'throttle' => 'For mange pรฅloggingsforsรธk. Vennligst prรธv igjen om :seconds sekunder.', - ]; diff --git a/resources/lang/nb-NO/passwords.php b/resources/lang/nb-NO/passwords.php index 63b56db..37333d8 100644 --- a/resources/lang/nb-NO/passwords.php +++ b/resources/lang/nb-NO/passwords.php @@ -18,5 +18,5 @@ return [ 'throttled' => 'Vennligst vent fรธr du prรธver igjen.', 'token' => 'Denne tilbakestillingskoden for passordet er ugyldig.', 'user' => 'Vi finner ingen bruker med den e-postadressen.', - + ]; diff --git a/resources/lang/nb-NO/validation.php b/resources/lang/nb-NO/validation.php index 96414ea..c56a999 100644 --- a/resources/lang/nb-NO/validation.php +++ b/resources/lang/nb-NO/validation.php @@ -117,7 +117,7 @@ return [ 'unique' => ':attribute er allerede tatt.', 'uploaded' => ':attribute kunne ikke lastes opp.', 'url' => ':attribute-formatet er ugyldig.', - 'uuid' => ':attribute mรฅ vรฆre en gyldig UUID.', + 'uuid' => ':attribute mรฅ vรฆre en gyldig UUID.', /* |-------------------------------------------------------------------------- diff --git a/resources/lang/nb-NO/verification.php b/resources/lang/nb-NO/verification.php index 1883f34..be5bfca 100644 --- a/resources/lang/nb-NO/verification.php +++ b/resources/lang/nb-NO/verification.php @@ -1,15 +1,15 @@ 'Credenciais informadas nรฃo correspondem com nossos registros.', + 'failed' => 'Credenciais informadas nรฃo correspondem com nossos registros.', 'throttle' => 'Vocรช realizou muitas tentativas de login. Por favor, tente novamente em :seconds segundos.', ]; diff --git a/resources/lang/pt-BR/pagination.php b/resources/lang/pt-BR/pagination.php index f1c0a7c..f955dd1 100644 --- a/resources/lang/pt-BR/pagination.php +++ b/resources/lang/pt-BR/pagination.php @@ -13,5 +13,5 @@ return [ */ 'previous' => '« Anterior', - 'next' => 'Prรณxima »', + 'next' => 'Prรณxima »', ]; diff --git a/resources/lang/pt-BR/passwords.php b/resources/lang/pt-BR/passwords.php index 6d57d48..e1822e7 100644 --- a/resources/lang/pt-BR/passwords.php +++ b/resources/lang/pt-BR/passwords.php @@ -13,8 +13,8 @@ return [ */ 'password' => 'A senha deve conter pelo menos oito caracteres e ser igual ร  confirmaรงรฃo.', - 'reset' => 'Sua senha foi redefinida!', - 'sent' => 'Enviamos um link para redefinir a sua senha por e-mail.', - 'token' => 'Esse cรณdigo de redefiniรงรฃo de senha รฉ invรกlido.', - 'user' => 'Nรฃo conseguimos encontrar nenhum usuรกrio com o endereรงo de e-mail informado.', + 'reset' => 'Sua senha foi redefinida!', + 'sent' => 'Enviamos um link para redefinir a sua senha por e-mail.', + 'token' => 'Esse cรณdigo de redefiniรงรฃo de senha รฉ invรกlido.', + 'user' => 'Nรฃo conseguimos encontrar nenhum usuรกrio com o endereรงo de e-mail informado.', ]; diff --git a/resources/lang/pt-BR/validation.php b/resources/lang/pt-BR/validation.php index 2193cbe..fd98696 100644 --- a/resources/lang/pt-BR/validation.php +++ b/resources/lang/pt-BR/validation.php @@ -12,109 +12,109 @@ return [ | */ - 'accepted' => 'O campo :attribute deve ser aceito.', - 'active_url' => 'O campo :attribute deve conter uma URL vรกlida.', - 'after' => 'O campo :attribute deve conter uma data posterior a :date.', - 'after_or_equal' => 'O campo :attribute deve conter uma data superior ou igual a :date.', - 'alpha' => 'O campo :attribute deve conter apenas letras.', - 'alpha_dash' => 'O campo :attribute deve conter apenas letras, nรบmeros e traรงos.', - 'alpha_num' => 'O campo :attribute deve conter apenas letras e nรบmeros .', - 'array' => 'O campo :attribute deve conter um array.', - 'before' => 'O campo :attribute deve conter uma data anterior a :date.', - 'before_or_equal' => 'O campo :attribute deve conter uma data inferior ou igual a :date.', - 'between' => [ + 'accepted' => 'O campo :attribute deve ser aceito.', + 'active_url' => 'O campo :attribute deve conter uma URL vรกlida.', + 'after' => 'O campo :attribute deve conter uma data posterior a :date.', + 'after_or_equal' => 'O campo :attribute deve conter uma data superior ou igual a :date.', + 'alpha' => 'O campo :attribute deve conter apenas letras.', + 'alpha_dash' => 'O campo :attribute deve conter apenas letras, nรบmeros e traรงos.', + 'alpha_num' => 'O campo :attribute deve conter apenas letras e nรบmeros .', + 'array' => 'O campo :attribute deve conter um array.', + 'before' => 'O campo :attribute deve conter uma data anterior a :date.', + 'before_or_equal' => 'O campo :attribute deve conter uma data inferior ou igual a :date.', + 'between' => [ 'numeric' => 'O campo :attribute deve conter um nรบmero entre :min e :max.', - 'file' => 'O campo :attribute deve conter um arquivo de :min a :max kilobytes.', - 'string' => 'O campo :attribute deve conter entre :min a :max caracteres.', - 'array' => 'O campo :attribute deve conter de :min a :max itens.', + 'file' => 'O campo :attribute deve conter um arquivo de :min a :max kilobytes.', + 'string' => 'O campo :attribute deve conter entre :min a :max caracteres.', + 'array' => 'O campo :attribute deve conter de :min a :max itens.', ], - 'boolean' => 'O campo :attribute deve conter o valor verdadeiro ou falso.', - 'confirmed' => 'A confirmaรงรฃo para o campo :attribute nรฃo coincide.', - 'date' => 'O campo :attribute nรฃo contรฉm uma data vรกlida.', - 'date_equals' => 'O campo :attribute deve ser uma data igual a :date.', - 'date_format' => 'A data informada para o campo :attribute nรฃo respeita o formato :format.', - 'different' => 'Os campos :attribute e :other devem conter valores diferentes.', - 'digits' => 'O campo :attribute deve conter :digits dรญgitos.', - 'digits_between' => 'O campo :attribute deve conter entre :min a :max dรญgitos.', - 'dimensions' => 'O valor informado para o campo :attribute nรฃo รฉ uma dimensรฃo de imagem vรกlida.', - 'distinct' => 'O campo :attribute contรฉm um valor duplicado.', - 'email' => 'O campo :attribute nรฃo contรฉm um endereรงo de email vรกlido.', - 'ends_with' => 'The :attribute must end with one of the following: :values', - 'exists' => 'O valor selecionado para o campo :attribute รฉ invรกlido.', - 'file' => 'O campo :attribute deve conter um arquivo.', - 'filled' => 'O campo :attribute รฉ obrigatรณrio.', - 'gt' => [ + 'boolean' => 'O campo :attribute deve conter o valor verdadeiro ou falso.', + 'confirmed' => 'A confirmaรงรฃo para o campo :attribute nรฃo coincide.', + 'date' => 'O campo :attribute nรฃo contรฉm uma data vรกlida.', + 'date_equals' => 'O campo :attribute deve ser uma data igual a :date.', + 'date_format' => 'A data informada para o campo :attribute nรฃo respeita o formato :format.', + 'different' => 'Os campos :attribute e :other devem conter valores diferentes.', + 'digits' => 'O campo :attribute deve conter :digits dรญgitos.', + 'digits_between' => 'O campo :attribute deve conter entre :min a :max dรญgitos.', + 'dimensions' => 'O valor informado para o campo :attribute nรฃo รฉ uma dimensรฃo de imagem vรกlida.', + 'distinct' => 'O campo :attribute contรฉm um valor duplicado.', + 'email' => 'O campo :attribute nรฃo contรฉm um endereรงo de email vรกlido.', + 'ends_with' => 'The :attribute must end with one of the following: :values', + 'exists' => 'O valor selecionado para o campo :attribute รฉ invรกlido.', + 'file' => 'O campo :attribute deve conter um arquivo.', + 'filled' => 'O campo :attribute รฉ obrigatรณrio.', + 'gt' => [ 'numeric' => 'O campo :attribute deve ser maior que :value.', - 'file' => 'O arquivo :attribute deve ser maior que :value kilobytes.', - 'string' => 'O campo :attribute deve ser maior que :value caracteres.', - 'array' => 'O campo :attribute deve ter mais que :value itens.', + 'file' => 'O arquivo :attribute deve ser maior que :value kilobytes.', + 'string' => 'O campo :attribute deve ser maior que :value caracteres.', + 'array' => 'O campo :attribute deve ter mais que :value itens.', ], - 'gte' => [ + 'gte' => [ 'numeric' => 'O campo :attribute deve ser maior ou igual a :value.', - 'file' => 'O arquivo :attribute deve ser maior ou igual a :value kilobytes.', - 'string' => 'O campo :attribute deve ser maior ou igual a :value caracteres.', - 'array' => 'O campo :attribute deve ter :value itens ou mais.', + 'file' => 'O arquivo :attribute deve ser maior ou igual a :value kilobytes.', + 'string' => 'O campo :attribute deve ser maior ou igual a :value caracteres.', + 'array' => 'O campo :attribute deve ter :value itens ou mais.', ], - 'image' => 'O campo :attribute deve conter uma imagem.', - 'in' => 'O campo :attribute nรฃo contรฉm um valor vรกlido.', - 'in_array' => 'O campo :attribute nรฃo existe em :other.', - 'integer' => 'O campo :attribute deve conter um nรบmero inteiro.', - 'ip' => 'O campo :attribute deve conter um IP vรกlido.', - 'ipv4' => 'O campo :attribute deve conter um IPv4 vรกlido.', - 'ipv6' => 'O campo :attribute deve conter um IPv6 vรกlido.', - 'json' => 'O campo :attribute deve conter uma string JSON vรกlida.', - 'lt' => [ + 'image' => 'O campo :attribute deve conter uma imagem.', + 'in' => 'O campo :attribute nรฃo contรฉm um valor vรกlido.', + 'in_array' => 'O campo :attribute nรฃo existe em :other.', + 'integer' => 'O campo :attribute deve conter um nรบmero inteiro.', + 'ip' => 'O campo :attribute deve conter um IP vรกlido.', + 'ipv4' => 'O campo :attribute deve conter um IPv4 vรกlido.', + 'ipv6' => 'O campo :attribute deve conter um IPv6 vรกlido.', + 'json' => 'O campo :attribute deve conter uma string JSON vรกlida.', + 'lt' => [ 'numeric' => 'O campo :attribute deve ser menor que :value.', - 'file' => 'O arquivo :attribute ser menor que :value kilobytes.', - 'string' => 'O campo :attribute deve ser menor que :value caracteres.', - 'array' => 'O campo :attribute deve ter menos que :value itens.', + 'file' => 'O arquivo :attribute ser menor que :value kilobytes.', + 'string' => 'O campo :attribute deve ser menor que :value caracteres.', + 'array' => 'O campo :attribute deve ter menos que :value itens.', ], - 'lte' => [ + 'lte' => [ 'numeric' => 'O campo :attribute deve ser menor ou igual a :value.', - 'file' => 'O arquivo :attribute ser menor ou igual a :value kilobytes.', - 'string' => 'O campo :attribute deve ser menor ou igual a :value caracteres.', - 'array' => 'O campo :attribute nรฃo deve ter mais que :value itens.', + 'file' => 'O arquivo :attribute ser menor ou igual a :value kilobytes.', + 'string' => 'O campo :attribute deve ser menor ou igual a :value caracteres.', + 'array' => 'O campo :attribute nรฃo deve ter mais que :value itens.', ], - 'max' => [ + 'max' => [ 'numeric' => 'O campo :attribute nรฃo pode conter um valor superior a :max.', - 'file' => 'O campo :attribute nรฃo pode conter um arquivo com mais de :max kilobytes.', - 'string' => 'O campo :attribute nรฃo pode conter mais de :max caracteres.', - 'array' => 'O campo :attribute deve conter no mรกximo :max itens.', + 'file' => 'O campo :attribute nรฃo pode conter um arquivo com mais de :max kilobytes.', + 'string' => 'O campo :attribute nรฃo pode conter mais de :max caracteres.', + 'array' => 'O campo :attribute deve conter no mรกximo :max itens.', ], - 'mimes' => 'O campo :attribute deve conter um arquivo do tipo: :values.', - 'mimetypes' => 'O campo :attribute deve conter um arquivo do tipo: :values.', - 'min' => [ + 'mimes' => 'O campo :attribute deve conter um arquivo do tipo: :values.', + 'mimetypes' => 'O campo :attribute deve conter um arquivo do tipo: :values.', + 'min' => [ 'numeric' => 'O campo :attribute deve conter um nรบmero superior ou igual a :min.', - 'file' => 'O campo :attribute deve conter um arquivo com no mรญnimo :min kilobytes.', - 'string' => 'O campo :attribute deve conter no mรญnimo :min caracteres.', - 'array' => 'O campo :attribute deve conter no mรญnimo :min itens.', + 'file' => 'O campo :attribute deve conter um arquivo com no mรญnimo :min kilobytes.', + 'string' => 'O campo :attribute deve conter no mรญnimo :min caracteres.', + 'array' => 'O campo :attribute deve conter no mรญnimo :min itens.', ], - 'not_in' => 'O campo :attribute contรฉm um valor invรกlido.', - 'not_regex' => 'O formato do valor :attribute รฉ invรกlido.', - 'numeric' => 'O campo :attribute deve conter um valor numรฉrico.', - 'present' => 'O campo :attribute deve estar presente.', - 'regex' => 'O formato do valor informado no campo :attribute รฉ invรกlido.', - 'required' => 'O campo :attribute รฉ obrigatรณrio.', - 'required_if' => 'O campo :attribute รฉ obrigatรณrio quando o valor do campo :other รฉ igual a :value.', - 'required_unless' => 'O campo :attribute รฉ obrigatรณrio a menos que :other esteja presente em :values.', - 'required_with' => 'O campo :attribute รฉ obrigatรณrio quando :values estรก presente.', - 'required_with_all' => 'O campo :attribute รฉ obrigatรณrio quando um dos :values estรก presente.', - 'required_without' => 'O campo :attribute รฉ obrigatรณrio quando :values nรฃo estรก presente.', + 'not_in' => 'O campo :attribute contรฉm um valor invรกlido.', + 'not_regex' => 'O formato do valor :attribute รฉ invรกlido.', + 'numeric' => 'O campo :attribute deve conter um valor numรฉrico.', + 'present' => 'O campo :attribute deve estar presente.', + 'regex' => 'O formato do valor informado no campo :attribute รฉ invรกlido.', + 'required' => 'O campo :attribute รฉ obrigatรณrio.', + 'required_if' => 'O campo :attribute รฉ obrigatรณrio quando o valor do campo :other รฉ igual a :value.', + 'required_unless' => 'O campo :attribute รฉ obrigatรณrio a menos que :other esteja presente em :values.', + 'required_with' => 'O campo :attribute รฉ obrigatรณrio quando :values estรก presente.', + 'required_with_all' => 'O campo :attribute รฉ obrigatรณrio quando um dos :values estรก presente.', + 'required_without' => 'O campo :attribute รฉ obrigatรณrio quando :values nรฃo estรก presente.', 'required_without_all' => 'O campo :attribute รฉ obrigatรณrio quando nenhum dos :values estรก presente.', - 'same' => 'Os campos :attribute e :other devem conter valores iguais.', - 'size' => [ + 'same' => 'Os campos :attribute e :other devem conter valores iguais.', + 'size' => [ 'numeric' => 'O campo :attribute deve conter o nรบmero :size.', - 'file' => 'O campo :attribute deve conter um arquivo com o tamanho de :size kilobytes.', - 'string' => 'O campo :attribute deve conter :size caracteres.', - 'array' => 'O campo :attribute deve conter :size itens.', + 'file' => 'O campo :attribute deve conter um arquivo com o tamanho de :size kilobytes.', + 'string' => 'O campo :attribute deve conter :size caracteres.', + 'array' => 'O campo :attribute deve conter :size itens.', ], - 'starts_with' => 'O campo :attribute deve comeรงar com um dos seguintes valores: :values', - 'string' => 'O campo :attribute deve ser uma string.', - 'timezone' => 'O campo :attribute deve conter um fuso horรกrio vรกlido.', - 'unique' => 'O valor informado para o campo :attribute jรก estรก em uso.', - 'uploaded' => 'Falha no Upload do arquivo :attribute.', - 'url' => 'O formato da URL informada para o campo :attribute รฉ invรกlido.', - 'uuid' => 'O campo :attribute deve ser um UUID vรกlido.', + 'starts_with' => 'O campo :attribute deve comeรงar com um dos seguintes valores: :values', + 'string' => 'O campo :attribute deve ser uma string.', + 'timezone' => 'O campo :attribute deve conter um fuso horรกrio vรกlido.', + 'unique' => 'O valor informado para o campo :attribute jรก estรก em uso.', + 'uploaded' => 'Falha no Upload do arquivo :attribute.', + 'url' => 'O formato da URL informada para o campo :attribute รฉ invรกlido.', + 'uuid' => 'O campo :attribute deve ser um UUID vรกlido.', /* |-------------------------------------------------------------------------- @@ -145,37 +145,37 @@ return [ */ 'attributes' => [ - 'address' => 'endereรงo', - 'age' => 'idade', - 'body' => 'conteรบdo', - 'city' => 'cidade', - 'country' => 'paรญs', - 'date' => 'data', - 'day' => 'dia', - 'description' => 'descriรงรฃo', - 'excerpt' => 'resumo', - 'first_name' => 'primeiro nome', - 'gender' => 'gรชnero', - 'hour' => 'hora', - 'last_name' => 'sobrenome', - 'message' => 'mensagem', - 'minute' => 'minuto', - 'mobile' => 'celular', - 'month' => 'mรชs', - 'name' => 'nome', + 'address' => 'endereรงo', + 'age' => 'idade', + 'body' => 'conteรบdo', + 'city' => 'cidade', + 'country' => 'paรญs', + 'date' => 'data', + 'day' => 'dia', + 'description' => 'descriรงรฃo', + 'excerpt' => 'resumo', + 'first_name' => 'primeiro nome', + 'gender' => 'gรชnero', + 'hour' => 'hora', + 'last_name' => 'sobrenome', + 'message' => 'mensagem', + 'minute' => 'minuto', + 'mobile' => 'celular', + 'month' => 'mรชs', + 'name' => 'nome', 'password_confirmation' => 'confirmaรงรฃo da senha', - 'password' => 'senha', - 'phone' => 'telefone', - 'second' => 'segundo', - 'sex' => 'sexo', - 'state' => 'estado', - 'subject' => 'assunto', - 'text' => 'texto', - 'time' => 'hora', - 'title' => 'tรญtulo', - 'username' => 'usuรกrio', - 'year' => 'ano', - 'email' => 'e-mail', - 'remember' => 'lembrar-me', + 'password' => 'senha', + 'phone' => 'telefone', + 'second' => 'segundo', + 'sex' => 'sexo', + 'state' => 'estado', + 'subject' => 'assunto', + 'text' => 'texto', + 'time' => 'hora', + 'title' => 'tรญtulo', + 'username' => 'usuรกrio', + 'year' => 'ano', + 'email' => 'e-mail', + 'remember' => 'lembrar-me', ], ]; diff --git a/resources/lang/zh-CN/pagination.php b/resources/lang/zh-CN/pagination.php index 5803847..daf09f9 100644 --- a/resources/lang/zh-CN/pagination.php +++ b/resources/lang/zh-CN/pagination.php @@ -12,5 +12,5 @@ return [ | */ 'previous' => '« ไธŠไธ€้กต', - 'next' => 'ไธ‹ไธ€้กต »', + 'next' => 'ไธ‹ไธ€้กต »', ]; diff --git a/resources/lang/zh-CN/validation.php b/resources/lang/zh-CN/validation.php index be3ac42..e64838d 100644 --- a/resources/lang/zh-CN/validation.php +++ b/resources/lang/zh-CN/validation.php @@ -47,7 +47,7 @@ return [ 'array' => ':attribute ็š„ๆœ€ๅคงไธชๆ•ฐไธบ :max ไธช', ], 'mimes' => ':attribute ็š„ๆ–‡ไปถ็ฑปๅž‹ๅฟ…้กปๆ˜ฏ:values', - 'mimetypes' => ':attribute ็š„ๆ–‡ไปถ็ฑปๅž‹ๅฟ…้กปๆ˜ฏ: :values.', + 'mimetypes' => ':attribute ็š„ๆ–‡ไปถ็ฑปๅž‹ๅฟ…้กปๆ˜ฏ: :values.', 'min' => [ 'numeric' => ':attribute ็š„ๆœ€ๅฐ้•ฟๅบฆไธบ :min ไฝ', 'string' => ':attribute ็š„ๆœ€ๅฐ้•ฟๅบฆไธบ :min ๅญ—็ฌฆ', diff --git a/routes/api.php b/routes/api.php index 9ae138f..d084d04 100644 --- a/routes/api.php +++ b/routes/api.php @@ -7,22 +7,22 @@ use App\Http\Controllers\Auth\RegisterController; use App\Http\Controllers\Auth\ResetPasswordController; use App\Http\Controllers\Auth\UserController; use App\Http\Controllers\Auth\VerificationController; +use App\Http\Controllers\Forms\FormController; +use App\Http\Controllers\Forms\FormStatsController; +use App\Http\Controllers\Forms\FormSubmissionController; +use App\Http\Controllers\Forms\Integration\FormZapierWebhookController; +use App\Http\Controllers\Forms\PublicFormController; +use App\Http\Controllers\Forms\RecordController; use App\Http\Controllers\Settings\PasswordController; use App\Http\Controllers\Settings\ProfileController; use App\Http\Controllers\SubscriptionController; -use App\Http\Controllers\Forms\FormStatsController; -use App\Http\Controllers\Forms\PublicFormController; -use App\Http\Controllers\Forms\FormSubmissionController; -use App\Http\Controllers\Forms\FormController; -use App\Http\Controllers\Forms\RecordController; -use App\Http\Controllers\WorkspaceController; use App\Http\Controllers\TemplateController; -use App\Http\Controllers\Forms\Integration\FormZapierWebhookController; +use App\Http\Controllers\WorkspaceController; use App\Http\Middleware\Form\ResolveFormMiddleware; use Illuminate\Http\Request; use Illuminate\Http\Response; -use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Route; +use Illuminate\Support\Facades\Storage; /* |-------------------------------------------------------------------------- @@ -61,18 +61,26 @@ Route::group(['middleware' => 'auth:api'], function () { Route::post('/create', [WorkspaceController::class, 'create'])->name('create'); Route::prefix('/{workspaceId}')->group(function () { - Route::get('/users', - [WorkspaceController::class, 'listUsers'])->name('users.index'); + Route::get( + '/users', + [WorkspaceController::class, 'listUsers'] + )->name('users.index'); Route::prefix('/databases')->name('databases.')->group(function () { - Route::get('/search/{search?}', - [WorkspaceController::class, 'searchDatabases'])->name('search'); - Route::get('/{database_id}', - [WorkspaceController::class, 'getDatabase'])->name('show'); + Route::get( + '/search/{search?}', + [WorkspaceController::class, 'searchDatabases'] + )->name('search'); + Route::get( + '/{database_id}', + [WorkspaceController::class, 'getDatabase'] + )->name('show'); }); - Route::get('/forms', - [FormController::class, 'index'])->name('forms.index'); + Route::get( + '/forms', + [FormController::class, 'index'] + )->name('forms.index'); Route::put('/custom-domains', [WorkspaceController::class, 'saveCustomDomain'])->name('save-custom-domains'); Route::delete('/', [WorkspaceController::class, 'delete'])->name('delete'); @@ -96,31 +104,45 @@ Route::group(['middleware' => 'auth:api'], function () { Route::delete('/{id}/records/{recordid}/delete', [RecordController::class, 'delete'])->name('records.delete'); // Form Admin tool - Route::put('/{id}/regenerate-link/{option}', - [FormController::class, 'regenerateLink']) + Route::put( + '/{id}/regenerate-link/{option}', + [FormController::class, 'regenerateLink'] + ) ->where('option', '(uuid|slug)') ->name('regenerate-link'); - Route::post('/{id}/duplicate', - [FormController::class, 'duplicate'])->name('duplicate'); + Route::post( + '/{id}/duplicate', + [FormController::class, 'duplicate'] + )->name('duplicate'); // Assets & uploaded files - Route::post('/assets/upload', - [FormController::class, 'uploadAsset'])->name('assets.upload'); - Route::get('/{id}/uploaded-file/{filename}', - [FormController::class, 'viewFile'])->name('uploaded_file'); + Route::post( + '/assets/upload', + [FormController::class, 'uploadAsset'] + )->name('assets.upload'); + Route::get( + '/{id}/uploaded-file/{filename}', + [FormController::class, 'viewFile'] + )->name('uploaded_file'); // Integrations - Route::post('/webhooks/zapier', - [FormZapierWebhookController::class, 'store'])->name('integrations.zapier-hooks.store'); - Route::delete('/webhooks/zapier/{id}', - [FormZapierWebhookController::class, 'delete'])->name('integrations.zapier-hooks.delete'); + Route::post( + '/webhooks/zapier', + [FormZapierWebhookController::class, 'store'] + )->name('integrations.zapier-hooks.store'); + Route::delete( + '/webhooks/zapier/{id}', + [FormZapierWebhookController::class, 'delete'] + )->name('integrations.zapier-hooks.delete'); }); }); Route::group(['middleware' => 'moderator', 'prefix' => 'admin'], function () { - Route::get('impersonate/{identifier}', - [\App\Http\Controllers\Admin\ImpersonationController::class, 'impersonate']); + Route::get( + 'impersonate/{identifier}', + [\App\Http\Controllers\Admin\ImpersonationController::class, 'impersonate'] + ); }); }); @@ -138,7 +160,6 @@ Route::group(['middleware' => 'guest:api'], function () { Route::get('oauth/{driver}/callback', [OAuthController::class, 'handleCallback'])->name('oauth.callback'); }); - Route::group(['prefix' => 'appsumo'], function () { Route::get('oauth/callback', [\App\Http\Controllers\Auth\AppSumoAuthController::class, 'handleCallback'])->name('appsumo.callback'); Route::post('webhook', [\App\Http\Controllers\Webhook\AppSumoController::class, 'handle'])->name('appsumo.webhook'); @@ -152,8 +173,10 @@ Route::prefix('forms')->name('forms.')->group(function () { Route::post('{slug}/answer', [PublicFormController::class, 'answer'])->name('answer'); // Form content endpoints (user lists, relation lists etc.) - Route::get('{slug}/users', - [PublicFormController::class, 'listUsers'])->name('users.index'); + Route::get( + '{slug}/users', + [PublicFormController::class, 'listUsers'] + )->name('users.index'); }); // Get form and submit @@ -200,12 +223,13 @@ Route::post( [\App\Http\Controllers\Content\FileUploadController::class, 'upload'] )->middleware([]); -Route::get('local/temp/{path}', function (Request $request, string $path){ - if (!$request->hasValidSignature()) { +Route::get('local/temp/{path}', function (Request $request, string $path) { + if (! $request->hasValidSignature()) { abort(401); } $response = Response::make(Storage::get($path), 200); - $response->header("Content-Type", Storage::mimeType($path)); + $response->header('Content-Type', Storage::mimeType($path)); + return $response; })->where('path', '(.*)')->name('local.temp'); diff --git a/tests/Browser/LoginTest.php b/tests/Browser/LoginTest.php index be30034..0f58b81 100644 --- a/tests/Browser/LoginTest.php +++ b/tests/Browser/LoginTest.php @@ -12,30 +12,28 @@ it('can login onboarded users', function () { $this->createUserWorkspace($user); $this->browse(function ($browser) use ($user) { - $browser->visit(new Login) + $browser->visit(new Login()) ->submit($user->email, 'password') ->assertPageIs(Home::class); }); }); -it('cannot login with invalid credentials',function() -{ +it('cannot login with invalid credentials', function () { $this->browse(function ($browser) { - $browser->visit(new Login) + $browser->visit(new Login()) ->submit('test@test.app', 'password') ->pause(100) ->assertSee('These credentials do not match our records.'); }); }); -it('can log out the user',function() -{ +it('can log out the user', function () { $user = User::factory()->create(); $this->browse(function ($browser) use ($user) { - $browser->visit(new Login) + $browser->visit(new Login()) ->submit($user->email, 'password') - ->on(new Home) + ->on(new Home()) ->clickLogout() ->assertPageIs(Login::class); }); diff --git a/tests/Browser/Pages/Home.php b/tests/Browser/Pages/Home.php index d8421b2..6af320b 100644 --- a/tests/Browser/Pages/Home.php +++ b/tests/Browser/Pages/Home.php @@ -19,7 +19,6 @@ class Home extends Page /** * Assert that the browser is on the page. * - * @param Browser $browser * @return void */ public function assert(Browser $browser) @@ -40,7 +39,7 @@ class Home extends Page /** * Click on the log out link. * - * @param \Laravel\Dusk\Browser $browser + * @param \Laravel\Dusk\Browser $browser * @return void */ public function clickLogout($browser) diff --git a/tests/Browser/Pages/HomePage.php b/tests/Browser/Pages/HomePage.php index 26bf174..c04a7f0 100644 --- a/tests/Browser/Pages/HomePage.php +++ b/tests/Browser/Pages/HomePage.php @@ -19,7 +19,6 @@ class HomePage extends Page /** * Assert that the browser is on the page. * - * @param \Laravel\Dusk\Browser $browser * @return void */ public function assert(Browser $browser) diff --git a/tests/Browser/Pages/Login.php b/tests/Browser/Pages/Login.php index ff7194b..51fa4f0 100644 --- a/tests/Browser/Pages/Login.php +++ b/tests/Browser/Pages/Login.php @@ -17,16 +17,16 @@ class Login extends Page /** * Submit the form with the given credentials. * - * @param \Laravel\Dusk\Browser $browser - * @param string $email - * @param string $password + * @param \Laravel\Dusk\Browser $browser + * @param string $email + * @param string $password * @return void */ public function submit($browser, $email, $password) { $browser->type('email', $email) - ->type('password', $password) - ->press('@btn_login') - ->pause(500); + ->type('password', $password) + ->press('@btn_login') + ->pause(500); } } diff --git a/tests/Browser/Pages/Onboarding.php b/tests/Browser/Pages/Onboarding.php index 9d19eb4..49a5545 100644 --- a/tests/Browser/Pages/Onboarding.php +++ b/tests/Browser/Pages/Onboarding.php @@ -19,7 +19,6 @@ class Onboarding extends Page /** * Assert that the browser is on the page. * - * @param Browser $browser * @return void */ public function assert(Browser $browser) diff --git a/tests/Browser/Pages/Page.php b/tests/Browser/Pages/Page.php index 0ddfb34..09b5a35 100644 --- a/tests/Browser/Pages/Page.php +++ b/tests/Browser/Pages/Page.php @@ -10,7 +10,6 @@ abstract class Page extends BasePage /** * Assert that the browser is on the page. * - * @param Browser $browser * @return void */ public function assert(Browser $browser) diff --git a/tests/Browser/Pages/Register.php b/tests/Browser/Pages/Register.php index b29f00c..5e7f897 100644 --- a/tests/Browser/Pages/Register.php +++ b/tests/Browser/Pages/Register.php @@ -17,8 +17,7 @@ class Register extends Page /** * Submit the form with the given data. * - * @param \Laravel\Dusk\Browser $browser - * @param array $data + * @param \Laravel\Dusk\Browser $browser * @return void */ public function submit($browser, array $data = []) diff --git a/tests/Browser/RegisterTest.php b/tests/Browser/RegisterTest.php index 927729a..0f6c94f 100644 --- a/tests/Browser/RegisterTest.php +++ b/tests/Browser/RegisterTest.php @@ -22,7 +22,7 @@ class RegisterTest extends DuskTestCase /** * Pick Random option from custom select - * @param Browser $browser + * * @throws \Facebook\WebDriver\Exception\TimeOutException */ public function selectHearAboutUsReason(Browser $browser) @@ -39,7 +39,7 @@ class RegisterTest extends DuskTestCase public function register_with_valid_data() { $this->browse(function (Browser $browser) { - $browser->visit(new Register); + $browser->visit(new Register()); $this->selectHearAboutUsReason($browser); $browser->submit([ 'name' => 'Test User', @@ -57,7 +57,7 @@ class RegisterTest extends DuskTestCase $user = User::factory()->create(); $this->browse(function (Browser $browser) use ($user) { - $browser->visit(new Register); + $browser->visit(new Register()); $this->selectHearAboutUsReason($browser); $browser->submit([ 'name' => 'Test User', diff --git a/tests/DuskTestCase.php b/tests/DuskTestCase.php index 824bc48..fd4f603 100644 --- a/tests/DuskTestCase.php +++ b/tests/DuskTestCase.php @@ -12,22 +12,24 @@ use Laravel\Dusk\TestCase as BaseTestCase; Browser::macro('assertPageIs', function ($page) { if (! $page instanceof Page) { - $page = new $page; + $page = new $page(); } + // waiting for location before asserting, because window.location.pathname may be updated asynchronously return $this->waitForLocation($page->url())->assertPathIs($page->url()); }); abstract class DuskTestCase extends BaseTestCase { - use DatabaseMigrations; use CreatesApplication; + use DatabaseMigrations; use TestHelpers; /** * Prepare for Dusk test execution. * * @beforeClass + * * @return void */ public static function prepare() @@ -42,15 +44,17 @@ abstract class DuskTestCase extends BaseTestCase */ protected function driver() { - $options = (new ChromeOptions)->addArguments([ + $options = (new ChromeOptions())->addArguments([ '--disable-gpu', '--headless', '--window-size=1920,1080', ]); return RemoteWebDriver::create( - 'http://localhost:9515', DesiredCapabilities::chrome()->setCapability( - ChromeOptions::CAPABILITY, $options + 'http://localhost:9515', + DesiredCapabilities::chrome()->setCapability( + ChromeOptions::CAPABILITY, + $options ) ); } diff --git a/tests/Feature/Forms/AnswerFormTest.php b/tests/Feature/Forms/AnswerFormTest.php index 5d0eeab..16fb750 100644 --- a/tests/Feature/Forms/AnswerFormTest.php +++ b/tests/Feature/Forms/AnswerFormTest.php @@ -10,7 +10,6 @@ it('can answer a form', function () { // TODO: generate random response given a form and un-skip })->skip('Need to finish writing a class to generated random responses'); - it('can submit form if close date is in future', function () { $user = $this->actingAsUser(); $workspace = $this->createUserWorkspace($user); @@ -23,7 +22,7 @@ it('can submit form if close date is in future', function () { ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form submission saved.' + 'message' => 'Form submission saved.', ]); }); @@ -48,12 +47,12 @@ it('can submit form till max submissions count is not reached at limit', functio $formData = FormSubmissionDataFactory::generateSubmissionData($form); // Can submit form - for($i=1;$i<=3;$i++){ + for ($i = 1; $i <= 3; $i++) { $this->postJson(route('forms.answer', $form->slug), $formData) ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form submission saved.' + 'message' => 'Form submission saved.', ]); } @@ -66,7 +65,7 @@ it('can not open draft form', function () { $user = $this->actingAsUser(); $workspace = $this->createUserWorkspace($user); $form = $this->createForm($user, $workspace, [ - 'visibility' => 'draft' + 'visibility' => 'draft', ]); $this->getJson(route('forms.show', $form->slug)) @@ -77,7 +76,7 @@ it('can not submit draft form', function () { $user = $this->actingAsUser(); $workspace = $this->createUserWorkspace($user); $form = $this->createForm($user, $workspace, [ - 'visibility' => 'draft' + 'visibility' => 'draft', ]); $formData = FormSubmissionDataFactory::generateSubmissionData($form); @@ -89,7 +88,7 @@ it('can not submit visibility closed form', function () { $user = $this->actingAsUser(); $workspace = $this->createUserWorkspace($user); $form = $this->createForm($user, $workspace, [ - 'visibility' => 'closed' + 'visibility' => 'closed', ]); $formData = FormSubmissionDataFactory::generateSubmissionData($form); @@ -104,10 +103,11 @@ it('can not submit form with past dates', function () { $submissionData = []; $form->properties = collect($form->properties)->map(function ($property) use (&$submissionData) { - if(in_array($property['type'], ['date'])){ - $property["disable_past_dates"] = true; + if (in_array($property['type'], ['date'])) { + $property['disable_past_dates'] = true; $submissionData[$property['id']] = now()->subDays(4)->format('Y-m-d'); } + return $property; })->toArray(); $form->update(); @@ -117,7 +117,7 @@ it('can not submit form with past dates', function () { $this->postJson(route('forms.answer', $form->slug), $formData) ->assertStatus(422) ->assertJson([ - 'message' => 'The Date must be a date after or equal to today.' + 'message' => 'The Date must be a date after or equal to today.', ]); }); @@ -128,10 +128,11 @@ it('can not submit form with future dates', function () { $submissionData = []; $form->properties = collect($form->properties)->map(function ($property) use (&$submissionData) { - if(in_array($property['type'], ['date'])){ - $property["disable_future_dates"] = true; + if (in_array($property['type'], ['date'])) { + $property['disable_future_dates'] = true; $submissionData[$property['id']] = now()->addDays(4)->format('Y-m-d'); } + return $property; })->toArray(); $form->update(); @@ -141,6 +142,6 @@ it('can not submit form with future dates', function () { $this->postJson(route('forms.answer', $form->slug), $formData) ->assertStatus(422) ->assertJson([ - 'message' => 'The Date must be a date before or equal to today.' + 'message' => 'The Date must be a date before or equal to today.', ]); }); diff --git a/tests/Feature/Forms/CleanDatabaseTest.php b/tests/Feature/Forms/CleanDatabaseTest.php index 22ba172..f16d7b9 100644 --- a/tests/Feature/Forms/CleanDatabaseTest.php +++ b/tests/Feature/Forms/CleanDatabaseTest.php @@ -1,6 +1,6 @@ actingAsUser(); @@ -8,7 +8,7 @@ it('check form statistic for views & submissions counts', function () { $form = $this->createForm($user, $workspace, []); // Create 10 views & submissions (in the past of 1 day so that it's cleaned) - for($i=1;$i<=10;$i++){ + for ($i = 1; $i <= 10; $i++) { $submission = $form->submissions()->create(); $submission->created_at = now()->subDay(); $submission->save(); @@ -29,7 +29,7 @@ it('check form statistic for views & submissions counts', function () { Artisan::call('forms:database-cleanup'); // Create 5 views & submissions - for($i=1;$i<=5;$i++){ + for ($i = 1; $i <= 5; $i++) { $form->views()->create(); $form->submissions()->create(); } @@ -41,8 +41,8 @@ it('check form statistic for views & submissions counts', function () { expect($form->views()->count())->toBe(5); expect($form->submissions()->count())->toBe(16); expect(count($statistics))->toBe(2); // 1 per day for 2 different dates - expect($statistics[0]["date"])->toBe(now()->subDays(2)->toDateString()); - expect($statistics[0]["data"])->toBe(["views"=>1,"submissions"=>1]); - expect($statistics[1]["date"])->toBe(now()->subDay()->toDateString()); - expect($statistics[1]["data"])->toBe(["views"=>10,"submissions"=>10]); -}); \ No newline at end of file + expect($statistics[0]['date'])->toBe(now()->subDays(2)->toDateString()); + expect($statistics[0]['data'])->toBe(['views' => 1, 'submissions' => 1]); + expect($statistics[1]['date'])->toBe(now()->subDay()->toDateString()); + expect($statistics[1]['data'])->toBe(['views' => 10, 'submissions' => 10]); +}); diff --git a/tests/Feature/Forms/ConfirmationEmailTest.php b/tests/Feature/Forms/ConfirmationEmailTest.php index 2f7683f..6776b7b 100644 --- a/tests/Feature/Forms/ConfirmationEmailTest.php +++ b/tests/Feature/Forms/ConfirmationEmailTest.php @@ -1,7 +1,7 @@ actingAsUser(); @@ -17,7 +17,7 @@ it('creates confirmation emails with the submitted data', function () { $formData = [ collect($form->properties)->first(function ($property) { return $property['type'] == 'email'; - })["id"] => "test@test.com", + })['id'] => 'test@test.com', ]; $event = new \App\Events\Forms\FormSubmitted($form, $formData); $mailable = new SubmissionConfirmationMail($event); @@ -40,7 +40,7 @@ it('creates confirmation emails without the submitted data', function () { $formData = [ collect($form->properties)->first(function ($property) { return $property['type'] == 'email'; - })["id"] => "test@test.com", + })['id'] => 'test@test.com', ]; $event = new \App\Events\Forms\FormSubmitted($form, $formData); $mailable = new SubmissionConfirmationMail($event); @@ -61,7 +61,7 @@ it('sends a confirmation email if needed', function () { return $property['type'] == 'email'; }); $formData = [ - $emailProperty["id"] => "test@test.com", + $emailProperty['id'] => 'test@test.com', ]; Mail::fake(); @@ -70,13 +70,15 @@ it('sends a confirmation email if needed', function () { ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form submission saved.' + 'message' => 'Form submission saved.', ]); - Mail::assertQueued(SubmissionConfirmationMail::class, - function (SubmissionConfirmationMail $mail) use ($formData, $emailProperty) { - return $mail->hasTo("test@test.com"); - }); + Mail::assertQueued( + SubmissionConfirmationMail::class, + function (SubmissionConfirmationMail $mail) { + return $mail->hasTo('test@test.com'); + } + ); }); it('does not send a confirmation email if not needed', function () { @@ -89,7 +91,7 @@ it('does not send a confirmation email if not needed', function () { return $property['type'] == 'email'; }); $formData = [ - $emailProperty["id"] => "test@test.com", + $emailProperty['id'] => 'test@test.com', ]; Mail::fake(); @@ -98,12 +100,13 @@ it('does not send a confirmation email if not needed', function () { ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form submission saved.' + 'message' => 'Form submission saved.', ]); - Mail::assertNotQueued(SubmissionConfirmationMail::class, - function (SubmissionConfirmationMail $mail) use ($formData, $emailProperty) { - return $mail->hasTo("test@test.com"); - }); + Mail::assertNotQueued( + SubmissionConfirmationMail::class, + function (SubmissionConfirmationMail $mail) { + return $mail->hasTo('test@test.com'); + } + ); }); - diff --git a/tests/Feature/Forms/CreateDynamicSelectOptionTest.php b/tests/Feature/Forms/CreateDynamicSelectOptionTest.php index 3cc78f5..fc0ebac 100644 --- a/tests/Feature/Forms/CreateDynamicSelectOptionTest.php +++ b/tests/Feature/Forms/CreateDynamicSelectOptionTest.php @@ -1,17 +1,19 @@ actingAsUser(); $workspace = $this->createUserWorkspace($user); $form = $this->createForm($user, $workspace); - + $selectionsPreData = []; $form->properties = collect($form->properties)->map(function ($property) use (&$selectionsPreData) { - if(in_array($property['type'], ['select','multi_select'])){ - $property["allow_creation"] = true; - $selectionsPreData[$property['id']] = ($property['type'] == "select") ? "New single select - ".time() : ["New multi select - ".time()]; + if (in_array($property['type'], ['select', 'multi_select'])) { + $property['allow_creation'] = true; + $selectionsPreData[$property['id']] = ($property['type'] == 'select') ? 'New single select - '.time() : ['New multi select - '.time()]; } + return $property; })->toArray(); $form->update(); @@ -21,6 +23,6 @@ it('can submit form with dyanamic select option', function () { ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form submission saved.' + 'message' => 'Form submission saved.', ]); -}); \ No newline at end of file +}); diff --git a/tests/Feature/Forms/FormCaptchaTest.php b/tests/Feature/Forms/FormCaptchaTest.php index b56b9e9..7b33082 100644 --- a/tests/Feature/Forms/FormCaptchaTest.php +++ b/tests/Feature/Forms/FormCaptchaTest.php @@ -16,5 +16,5 @@ it('create form with captcha and raise validation issue', function () { 'Please complete the captcha.', ], ], - ]); + ]); }); diff --git a/tests/Feature/Forms/FormLogicTest.php b/tests/Feature/Forms/FormLogicTest.php index ce46ae1..4568245 100644 --- a/tests/Feature/Forms/FormLogicTest.php +++ b/tests/Feature/Forms/FormLogicTest.php @@ -1,6 +1,6 @@ actingAsUser(); @@ -8,103 +8,100 @@ it('create form with logic', function () { $form = $this->createForm($user, $workspace, [ 'properties' => [ [ - 'id' => "title", - 'name' => "Name", + 'id' => 'title', + 'name' => 'Name', 'type' => 'title', 'hidden' => false, 'required' => true, 'logic' => [ - "conditions" => [ - "operatorIdentifier"=> "and", - "children"=> [ + 'conditions' => [ + 'operatorIdentifier' => 'and', + 'children' => [ [ - "identifier"=> "email", - "value"=> [ - "operator"=> "is_empty", - "property_meta"=> [ - 'id'=> "93ea3198-353f-440b-8dc9-2ac9a7bee124", - "type"=> "email", + 'identifier' => 'email', + 'value' => [ + 'operator' => 'is_empty', + 'property_meta' => [ + 'id' => '93ea3198-353f-440b-8dc9-2ac9a7bee124', + 'type' => 'email', ], - "value"=> true - ] - ] - ] + 'value' => true, + ], + ], + ], ], - "actions" => ['make-it-optional'] - ] - ] + 'actions' => ['make-it-optional'], + ], + ], ], ]); - $this->getJson(route('forms.show', $form->slug)) ->assertSuccessful() ->assertJson(function (AssertableJson $json) use ($form) { return $json->where('id', $form->id) - ->where('properties', function($values){ - return (count($values[0]['logic']) > 0); + ->where('properties', function ($values) { + return count($values[0]['logic']) > 0; }) ->etc(); }); // Should submit form - $forData = ['93ea3198-353f-440b-8dc9-2ac9a7bee124' => ""]; + $forData = ['93ea3198-353f-440b-8dc9-2ac9a7bee124' => '']; $this->postJson(route('forms.answer', $form->slug), $forData) ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form submission saved.' + 'message' => 'Form submission saved.', ]); }); - it('create form with multi select logic', function () { $user = $this->actingAsUser(); $workspace = $this->createUserWorkspace($user); $form = $this->createForm($user, $workspace, [ 'properties' => [ [ - 'id' => "title", - 'name' => "Name", + 'id' => 'title', + 'name' => 'Name', 'type' => 'title', 'hidden' => false, 'required' => false, 'logic' => [ - "conditions" => [ - "operatorIdentifier"=> "and", - "children"=> [ + 'conditions' => [ + 'operatorIdentifier' => 'and', + 'children' => [ [ - "identifier"=> "multi_select", - "value"=> [ - "operator"=> "contains", - "property_meta"=> [ - 'id'=> "93ea3198-353f-440b-8dc9-2ac9a7bee124", - "type"=> "multi_select", + 'identifier' => 'multi_select', + 'value' => [ + 'operator' => 'contains', + 'property_meta' => [ + 'id' => '93ea3198-353f-440b-8dc9-2ac9a7bee124', + 'type' => 'multi_select', ], - "value"=> 'One' - ] - ] - ] + 'value' => 'One', + ], + ], + ], ], - "actions" => ['require-answer'] - ] - ] + 'actions' => ['require-answer'], + ], + ], ], ]); - $this->getJson(route('forms.show', $form->slug)) ->assertSuccessful() ->assertJson(function (AssertableJson $json) use ($form) { return $json->where('id', $form->id) - ->where('properties', function($values){ - return (count($values[0]['logic']) > 0); + ->where('properties', function ($values) { + return count($values[0]['logic']) > 0; }) ->etc(); }); // Should submit form - $forData = ['93ea3198-353f-440b-8dc9-2ac9a7bee124' => ["One"]]; + $forData = ['93ea3198-353f-440b-8dc9-2ac9a7bee124' => ['One']]; $this->postJson(route('forms.answer', $form->slug), $forData) ->assertStatus(422) ->assertJson([ @@ -114,5 +111,5 @@ it('create form with multi select logic', function () { 'The Name field is required.', ], ], - ]); + ]); }); diff --git a/tests/Feature/Forms/FormPasswordTest.php b/tests/Feature/Forms/FormPasswordTest.php index 03d2650..8b93174 100644 --- a/tests/Feature/Forms/FormPasswordTest.php +++ b/tests/Feature/Forms/FormPasswordTest.php @@ -1,10 +1,10 @@ password = "12345"; + $this->password = '12345'; $user = $this->actingAsUser(); $workspace = $this->createUserWorkspace($user); $this->form = $this->createForm($user, $workspace, [ @@ -13,7 +13,6 @@ beforeEach(function () { $this->formData = FormSubmissionDataFactory::generateSubmissionData($this->form); }); - it('can allow form owner to access and submit form without password', function () { // As Form Owner so can access form without password $this->getJson(route('forms.show', $this->form->slug)) @@ -30,7 +29,7 @@ it('can allow form owner to access and submit form without password', function ( ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form submission saved.' + 'message' => 'Form submission saved.', ]); }); @@ -54,26 +53,26 @@ it('can not submit form without password for guest user', function () { ->assertStatus(403) ->assertJson([ 'status' => 'Unauthorized', - 'message' => 'Form is protected.' + 'message' => 'Form is protected.', ]); }); it('can not submit form with wrong password for guest user', function () { $this->actingAsGuest(); - $this->withHeaders(['form-password'=>hash('sha256', 'WRONGPASSWORD')]) + $this->withHeaders(['form-password' => hash('sha256', 'WRONGPASSWORD')]) ->postJson(route('forms.answer', $this->form->slug), $this->formData) ->assertStatus(403) ->assertJson([ 'status' => 'Unauthorized', - 'message' => 'Form is protected.' + 'message' => 'Form is protected.', ]); }); it('can access form with right password for guest user', function () { $this->actingAsGuest(); - $this->withHeaders(['form-password'=>hash('sha256', $this->password)]) + $this->withHeaders(['form-password' => hash('sha256', $this->password)]) ->getJson(route('forms.show', $this->form->slug)) ->assertSuccessful() ->assertJson(function (AssertableJson $json) { @@ -87,11 +86,11 @@ it('can access form with right password for guest user', function () { it('can submit form with right password for guest user', function () { $this->actingAsGuest(); - $this->withHeaders(['form-password'=>hash('sha256', $this->password)]) + $this->withHeaders(['form-password' => hash('sha256', $this->password)]) ->postJson(route('forms.answer', $this->form->slug), $this->formData) ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form submission saved.' + 'message' => 'Form submission saved.', ]); }); diff --git a/tests/Feature/Forms/FormPropertyLogicTest.php b/tests/Feature/Forms/FormPropertyLogicTest.php index 41a4c86..01ed161 100644 --- a/tests/Feature/Forms/FormPropertyLogicTest.php +++ b/tests/Feature/Forms/FormPropertyLogicTest.php @@ -1,202 +1,201 @@ - ['array', 'nullable', new FormPropertyLogicRule()] + 'properties.*.logic' => ['array', 'nullable', new FormPropertyLogicRule()], ]; - + $data = [ 'properties' => [ [ - 'id' => "title", - 'name' => "Name", + 'id' => 'title', + 'name' => 'Name', 'type' => 'title', 'hidden' => false, 'required' => false, 'logic' => [ - "conditions" => null, - "actions" => [] - ] - ] - ] + 'conditions' => null, + 'actions' => [], + ], + ], + ], ]; $validatorObj = $this->app['validator']->make($data, $rules); $this->assertTrue($validatorObj->passes()); - $data = [ 'properties' => [ [ - 'id' => "title", - 'name' => "Name", + 'id' => 'title', + 'name' => 'Name', 'type' => 'title', 'hidden' => true, 'required' => false, 'logic' => [ - "conditions" => [ - "operatorIdentifier"=> "and", - "children"=> [ + 'conditions' => [ + 'operatorIdentifier' => 'and', + 'children' => [ [ - "identifier"=> "title", - "value"=> [ - "operator"=> "equals", - "property_meta"=> [ - "id"=> "title", - "type"=> "text" + 'identifier' => 'title', + 'value' => [ + 'operator' => 'equals', + 'property_meta' => [ + 'id' => 'title', + 'type' => 'text', ], - "value"=> "TEST" - ] - ] - ] + 'value' => 'TEST', + ], + ], + ], ], - "actions" => ['hide-block'] - ] - ] - ] + 'actions' => ['hide-block'], + ], + ], + ], ]; $validatorObj = $this->app['validator']->make($data, $rules); $this->assertFalse($validatorObj->passes()); - expect($validatorObj->errors()->messages()['properties.0.logic'][0])->toBe("The logic actions for Name are not valid."); + expect($validatorObj->errors()->messages()['properties.0.logic'][0])->toBe('The logic actions for Name are not valid.'); $data = [ 'properties' => [ [ - 'id' => "text", - 'name' => "Custom Test", + 'id' => 'text', + 'name' => 'Custom Test', 'type' => 'nf-text', 'logic' => [ - "conditions" => [ - "operatorIdentifier"=> "and", - "children"=> [ + 'conditions' => [ + 'operatorIdentifier' => 'and', + 'children' => [ [ - "identifier"=> "title", - "value"=> [ - "operator"=> "equals", - "property_meta"=> [ - "id"=> "title", - "type"=> "text" + 'identifier' => 'title', + 'value' => [ + 'operator' => 'equals', + 'property_meta' => [ + 'id' => 'title', + 'type' => 'text', ], - "value"=> "TEST" - ] - ] - ] + 'value' => 'TEST', + ], + ], + ], ], - "actions" => ['require-answer'] - ] - ] - ] + 'actions' => ['require-answer'], + ], + ], + ], ]; $validatorObj = $this->app['validator']->make($data, $rules); $this->assertFalse($validatorObj->passes()); - expect($validatorObj->errors()->messages()['properties.0.logic'][0])->toBe("The logic actions for Custom Test are not valid."); + expect($validatorObj->errors()->messages()['properties.0.logic'][0])->toBe('The logic actions for Custom Test are not valid.'); }); - it('can validate form logic rules for conditions', function () { $rules = [ - 'properties.*.logic' => ['array', 'nullable', new FormPropertyLogicRule()] + 'properties.*.logic' => ['array', 'nullable', new FormPropertyLogicRule()], ]; - + $data = [ 'properties' => [ [ - 'id' => "title", - 'name' => "Name", + 'id' => 'title', + 'name' => 'Name', 'type' => 'text', 'hidden' => false, 'required' => false, 'logic' => [ - "conditions" => [ - "operatorIdentifier"=> "and", - "children"=> [ + 'conditions' => [ + 'operatorIdentifier' => 'and', + 'children' => [ [ - "identifier"=> "title", - "value"=> [ - "operator"=> "equals", - "property_meta"=> [ - "id"=> "title", - "type"=> "text" + 'identifier' => 'title', + 'value' => [ + 'operator' => 'equals', + 'property_meta' => [ + 'id' => 'title', + 'type' => 'text', ], - "value"=> "TEST" - ] - ] - ] + 'value' => 'TEST', + ], + ], + ], ], - "actions" => ['hide-block'] - ] - ] - ] + 'actions' => ['hide-block'], + ], + ], + ], ]; - + $validatorObj = $this->app['validator']->make($data, $rules); $this->assertTrue($validatorObj->passes()); $data = [ 'properties' => [ [ - 'id' => "title", - 'name' => "Name", + 'id' => 'title', + 'name' => 'Name', 'type' => 'text', 'hidden' => false, 'required' => false, 'logic' => [ - "conditions" => [ - "operatorIdentifier"=> "and", - "children"=> [ + 'conditions' => [ + 'operatorIdentifier' => 'and', + 'children' => [ [ - "identifier"=> "title", - "value"=> [ - "operator"=> "starts_with", - "property_meta"=> [ - "id"=> "title", - "type"=> "text" + 'identifier' => 'title', + 'value' => [ + 'operator' => 'starts_with', + 'property_meta' => [ + 'id' => 'title', + 'type' => 'text', ], - ] - ] - ] + ], + ], + ], ], - "actions" => ['hide-block'] - ] - ] - ] + 'actions' => ['hide-block'], + ], + ], + ], ]; - + $validatorObj = $this->app['validator']->make($data, $rules); $this->assertFalse($validatorObj->passes()); - expect($validatorObj->errors()->messages()['properties.0.logic'][0])->toBe("The logic conditions for Name are not complete. Error detail(s): missing condition value"); + expect($validatorObj->errors()->messages()['properties.0.logic'][0])->toBe('The logic conditions for Name are not complete. Error detail(s): missing condition value'); $data = [ 'properties' => [ [ - 'id' => "title", - 'name' => "Name", + 'id' => 'title', + 'name' => 'Name', 'type' => 'text', 'hidden' => false, 'required' => false, 'logic' => [ - "conditions" => [ - "operatorIdentifier"=> null, - "children"=> [ + 'conditions' => [ + 'operatorIdentifier' => null, + 'children' => [ [ - "identifier"=> "title", - "value"=> [ - "operator"=> "starts_with", - "property_meta"=> [ - "id"=> "title", - "type"=> "text" + 'identifier' => 'title', + 'value' => [ + 'operator' => 'starts_with', + 'property_meta' => [ + 'id' => 'title', + 'type' => 'text', ], - ] - ] - ] + ], + ], + ], ], - "actions" => ['hide-block'] - ] - ] - ] + 'actions' => ['hide-block'], + ], + ], + ], ]; - + $validatorObj = $this->app['validator']->make($data, $rules); $this->assertFalse($validatorObj->passes()); - expect($validatorObj->errors()->messages()['properties.0.logic'][0])->toBe("The logic conditions for Name are not complete. Error detail(s): missing operator"); -}); \ No newline at end of file + expect($validatorObj->errors()->messages()['properties.0.logic'][0])->toBe('The logic conditions for Name are not complete. Error detail(s): missing operator'); +}); diff --git a/tests/Feature/Forms/FormStatTest.php b/tests/Feature/Forms/FormStatTest.php index af83211..7ba64bc 100644 --- a/tests/Feature/Forms/FormStatTest.php +++ b/tests/Feature/Forms/FormStatTest.php @@ -1,4 +1,5 @@ subDays($i); $dateString = $date->format('d-m-Y'); @@ -28,7 +29,7 @@ it('check formstat chart data', function () { Artisan::call('forms:database-cleanup'); // Create 5 views & submissions - for($i=1;$i<=5;$i++){ + for ($i = 1; $i <= 5; $i++) { $form->views()->create(); $form->submissions()->create(); @@ -43,20 +44,22 @@ it('check formstat chart data', function () { ->assertJson(function (\Illuminate\Testing\Fluent\AssertableJson $json) use ($views, $submissions) { return $json->whereType('views', 'array') ->whereType('submissions', 'array') - ->where('views', function($values) use ($views) { - foreach($values as $date=>$count){ - if((isset($views[$date]) && $views[$date] != $count) || (!isset($views[$date]) && $count != 0)){ + ->where('views', function ($values) use ($views) { + foreach ($values as $date => $count) { + if ((isset($views[$date]) && $views[$date] != $count) || (! isset($views[$date]) && $count != 0)) { return false; } } + return true; }) - ->where('submissions', function($values) use ($submissions) { - foreach($values as $date=>$count){ - if((isset($submissions[$date]) && $submissions[$date] != $count) || (!isset($submissions[$date]) && $count != 0)){ + ->where('submissions', function ($values) use ($submissions) { + foreach ($values as $date => $count) { + if ((isset($submissions[$date]) && $submissions[$date] != $count) || (! isset($submissions[$date]) && $count != 0)) { return false; } } + return true; }) ->etc(); diff --git a/tests/Feature/Forms/FormTest.php b/tests/Feature/Forms/FormTest.php index 0471ada..05af148 100644 --- a/tests/Feature/Forms/FormTest.php +++ b/tests/Feature/Forms/FormTest.php @@ -12,7 +12,7 @@ it('can create a contact form', function () { ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form created.' + 'message' => 'Form created.', ]); expect($workspace->forms()->count())->toBe(1); @@ -47,7 +47,7 @@ it('can update a form', function () { ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form updated.' + 'message' => 'Form updated.', ]); $this->assertDatabaseHas('forms', [ @@ -73,10 +73,13 @@ it('can regenerate a form url', function () { ->assertJson(function (AssertableJson $json) { return $json->where('type', 'success') ->where('form.slug', function ($value) { - if (!is_string($value) || (preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/', - $value) !== 1)) { + if (! is_string($value) || (preg_match( + '/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/', + $value + ) !== 1)) { return false; } + return true; }) ->etc(); @@ -103,7 +106,7 @@ it('can duplicate a form', function () { ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form successfully duplicated.' + 'message' => 'Form successfully duplicated.', ]); expect($user->forms()->count())->toBe(2); @@ -124,7 +127,7 @@ it('can delete a form', function () { ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form was deleted.' + 'message' => 'Form was deleted.', ]); expect($user->forms()->count())->toBe(0); expect($workspace->forms()->count())->toBe(0); @@ -134,7 +137,7 @@ it('can create form with dark mode', function () { $user = $this->actingAsUser(); $workspace = $this->createUserWorkspace($user); $form = $this->createForm($user, $workspace, [ - 'dark_mode' => "dark", + 'dark_mode' => 'dark', ]); $formData = (new \App\Http\Resources\FormResource($form))->toArray(request()); @@ -142,7 +145,7 @@ it('can create form with dark mode', function () { ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form created.' + 'message' => 'Form created.', ]); $this->getJson(route('forms.show', $form->slug)) diff --git a/tests/Feature/Forms/FormUpdateTest.php b/tests/Feature/Forms/FormUpdateTest.php index 1a0f446..928a6ee 100644 --- a/tests/Feature/Forms/FormUpdateTest.php +++ b/tests/Feature/Forms/FormUpdateTest.php @@ -11,7 +11,7 @@ it('can update form with existing record', function () { $nameProperty = collect($form->properties)->filter(function ($property) { return $property['name'] == 'Name'; - })->first(); + })->first(); $response = $this->postJson(route('forms.answer', $form->slug), [$nameProperty['id'] => 'Testing']) ->assertSuccessful() @@ -22,8 +22,8 @@ it('can update form with existing record', function () { $submissionId = $response->json('submission_id'); expect($submissionId)->toBeString(); - if($submissionId){ - $formData = FormSubmissionDataFactory::generateSubmissionData($form, ['submission_id'=>$submissionId, $nameProperty['id'] => 'Testing Updated']); + if ($submissionId) { + $formData = FormSubmissionDataFactory::generateSubmissionData($form, ['submission_id' => $submissionId, $nameProperty['id'] => 'Testing Updated']); $response = $this->postJson(route('forms.answer', $form->slug), $formData) ->assertSuccessful() ->assertJson([ @@ -35,7 +35,7 @@ it('can update form with existing record', function () { expect($submissionId2)->toBe($submissionId); $response = $this->getJson(route('forms.fetchSubmission', [$form->slug, $submissionId])) - ->assertSuccessful(); + ->assertSuccessful(); expect($response->json('data.'.$nameProperty['id']))->toBe('Testing Updated'); } }); diff --git a/tests/Feature/Forms/FormViewsTest.php b/tests/Feature/Forms/FormViewsTest.php index 0c068e5..df4fedc 100644 --- a/tests/Feature/Forms/FormViewsTest.php +++ b/tests/Feature/Forms/FormViewsTest.php @@ -17,7 +17,6 @@ it('can see form without counting view for form owner', function () { expect($form->views()->count())->toBe(0); }); - it('can see form and count view for guest', function () { $user = $this->actingAsUser(); $workspace = $this->createUserWorkspace($user); diff --git a/tests/Feature/Forms/UpdateWorkspaceSelectOptionJobTest.php b/tests/Feature/Forms/UpdateWorkspaceSelectOptionJobTest.php index 9d53f75..5b8db1f 100644 --- a/tests/Feature/Forms/UpdateWorkspaceSelectOptionJobTest.php +++ b/tests/Feature/Forms/UpdateWorkspaceSelectOptionJobTest.php @@ -1,6 +1,7 @@ actingAsUser(); @@ -12,7 +13,7 @@ it('can validate Update Workspace Select Option Job', function () { ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form submission saved.' + 'message' => 'Form submission saved.', ]); $formData = FormSubmissionDataFactory::generateSubmissionData($form); @@ -20,7 +21,7 @@ it('can validate Update Workspace Select Option Job', function () { ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form submission saved.' + 'message' => 'Form submission saved.', ]); }); @@ -30,6 +31,6 @@ it('can validate scope with active subscription', function () { $this->createProUser(); $this->createProUser(); $this->createUser(); - + expect(User::WithActiveSubscription()->count())->toBe(3); -}); \ No newline at end of file +}); diff --git a/tests/Feature/LoginTest.php b/tests/Feature/LoginTest.php index f7461e4..a766aa0 100644 --- a/tests/Feature/LoginTest.php +++ b/tests/Feature/LoginTest.php @@ -6,9 +6,9 @@ it('can login to Forms', function () { $user = User::factory()->create(); $this->postJson('/login', [ - 'email' => $user->email, - 'password' => 'password', - ]) + 'email' => $user->email, + 'password' => 'password', + ]) ->assertSuccessful() ->assertJsonStructure(['token', 'expires_in']) ->assertJson(['token_type' => 'bearer']); @@ -28,11 +28,10 @@ it('can log out', function () { ])->assertSuccessful(); $this->assertAuthenticated(); - $this->postJson("/logout") + $this->postJson('/logout') ->assertSuccessful(); $this->assertGuest(); - $this->getJson("/user") + $this->getJson('/user') ->assertStatus(401); }); - diff --git a/tests/Feature/RegisterTest.php b/tests/Feature/RegisterTest.php index 049a40a..5ad801e 100644 --- a/tests/Feature/RegisterTest.php +++ b/tests/Feature/RegisterTest.php @@ -1,7 +1,7 @@ 'google', 'password' => 'secret', 'password_confirmation' => 'secret', - 'agree_terms' => true + 'agree_terms' => true, ]) ->assertSuccessful() ->assertJsonStructure(['id', 'name', 'email']); $this->assertDatabaseHas('users', [ 'name' => 'Test User', - 'email' => 'test@test.app' + 'email' => 'test@test.app', ]); }); @@ -40,17 +40,17 @@ it('cannot register with disposable email', function () { 'dumliyupse@gufum.com', 'kcs79722@zslsz.com', 'pfizexwxtdifxupdhr@tpwlb.com', - 'qvj86ypqfm@email.edu.pl' + 'qvj86ypqfm@email.edu.pl', ]); $this->postJson('/register', [ - 'name' => 'Test disposable', - 'email' => $email, - 'hear_about_us' => 'google', - 'password' => 'secret', - 'password_confirmation' => 'secret', - 'agree_terms' => true - ]) + 'name' => 'Test disposable', + 'email' => $email, + 'hear_about_us' => 'google', + 'password' => 'secret', + 'password_confirmation' => 'secret', + 'agree_terms' => true, + ]) ->assertStatus(422) ->assertJsonValidationErrors(['email']) ->assertJson([ diff --git a/tests/Feature/SettingsTest.php b/tests/Feature/SettingsTest.php index 66c57bf..b9b86bc 100644 --- a/tests/Feature/SettingsTest.php +++ b/tests/Feature/SettingsTest.php @@ -2,31 +2,30 @@ use App\Models\User; use Illuminate\Support\Facades\Hash; -use Tests\TestCase; -it('update profile info',function() { - $this->actingAs($user = User::factory()->create()) - ->patchJson('/settings/profile', [ - 'name' => 'Test User', - 'email' => 'test@test.app', - ]) - ->assertSuccessful() - ->assertJsonStructure(['id', 'name', 'email']); - - $this->assertDatabaseHas('users', [ - 'id' => $user->id, +it('update profile info', function () { + $this->actingAs($user = User::factory()->create()) + ->patchJson('/settings/profile', [ 'name' => 'Test User', 'email' => 'test@test.app', - ]); + ]) + ->assertSuccessful() + ->assertJsonStructure(['id', 'name', 'email']); + + $this->assertDatabaseHas('users', [ + 'id' => $user->id, + 'name' => 'Test User', + 'email' => 'test@test.app', + ]); }); -it('update password',function() { - $this->actingAs($user = User::factory()->create()) - ->patchJson('/settings/password', [ - 'password' => 'updated', - 'password_confirmation' => 'updated', - ]) - ->assertSuccessful(); +it('update password', function () { + $this->actingAs($user = User::factory()->create()) + ->patchJson('/settings/password', [ + 'password' => 'updated', + 'password_confirmation' => 'updated', + ]) + ->assertSuccessful(); - $this->assertTrue(Hash::check('updated', $user->password)); + $this->assertTrue(Hash::check('updated', $user->password)); }); diff --git a/tests/Feature/Submissions/EditSubmissionTest.php b/tests/Feature/Submissions/EditSubmissionTest.php index 5bf2b0f..250846a 100644 --- a/tests/Feature/Submissions/EditSubmissionTest.php +++ b/tests/Feature/Submissions/EditSubmissionTest.php @@ -9,23 +9,23 @@ it('can update form submission', function () { $form = $this->createForm($user, $workspace, [ 'closes_at' => \Carbon\Carbon::now()->addDays(1)->toDateTimeString(), ]); - $formData = FormSubmissionDataFactory::generateSubmissionData($form, ['text' => 'John']); + $formData = FormSubmissionDataFactory::generateSubmissionData($form, ['text' => 'John']); $textFieldId = array_keys($formData)[0]; $updatedFormData = $formData; - $updatedFormTextValue = "Updated text"; + $updatedFormTextValue = 'Updated text'; $updatedFormData[$textFieldId] = $updatedFormTextValue; $this->postJson(route('forms.answer', $form->slug), $formData) ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form submission saved.' + 'message' => 'Form submission saved.', ]); $submission = $form->submissions()->first(); - $updateResponse = $this->putJson(route('open.forms.submissions.update', ['id'=>$form->id, 'submission_id' => $submission->id]), $updatedFormData) + $updateResponse = $this->putJson(route('open.forms.submissions.update', ['id' => $form->id, 'submission_id' => $submission->id]), $updatedFormData) ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Record successfully updated.' + 'message' => 'Record successfully updated.', ]); $expectedTextString = $updateResponse->json('data')['data'][$textFieldId]; expect($expectedTextString)->toBe($updatedFormTextValue); @@ -34,28 +34,26 @@ it('can update form submission', function () { }); it('cannot update form submission as non admin', function () { - $secondUser =$this->createUser(); + $secondUser = $this->createUser(); $user = $this->actingAsUser(); $workspace = $this->createUserWorkspace($user); $form = $this->makeForm($user, $workspace); $form = $this->createForm($user, $workspace, [ 'closes_at' => \Carbon\Carbon::now()->addDays(1)->toDateTimeString(), ]); - $formData = FormSubmissionDataFactory::generateSubmissionData($form, ['text' => 'John']); + $formData = FormSubmissionDataFactory::generateSubmissionData($form, ['text' => 'John']); $textFieldId = array_keys($formData)[0]; $updatedFormData = $formData; - $updatedFormTextValue = "Updated text"; + $updatedFormTextValue = 'Updated text'; $updatedFormData[$textFieldId] = $updatedFormTextValue; $this->postJson(route('forms.answer', $form->slug), $formData) ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Form submission saved.' + 'message' => 'Form submission saved.', ]); $submission = $form->submissions()->first(); $this->actingAs($secondUser); - $updateResponse = $this->putJson(route('open.forms.submissions.update', ['id'=>$form->id, 'submission_id' => $submission->id]), $updatedFormData) + $updateResponse = $this->putJson(route('open.forms.submissions.update', ['id' => $form->id, 'submission_id' => $submission->id]), $updatedFormData) ->assertStatus(403); }); - - diff --git a/tests/Feature/TemplateTest.php b/tests/Feature/TemplateTest.php index 624f827..c84d399 100644 --- a/tests/Feature/TemplateTest.php +++ b/tests/Feature/TemplateTest.php @@ -2,7 +2,7 @@ it('can create template', function () { $user = $this->createUser([ - 'email' => 'admin@opnform.com' + 'email' => 'admin@opnform.com', ]); $this->actingAsUser($user); @@ -19,12 +19,12 @@ it('can create template', function () { 'image_url' => 'https://d3ietpyl4f2d18.cloudfront.net/6c35a864-ee3a-4039-80a4-040b6c20ac60/img/pages/welcome/product_cover.jpg', 'publicly_listed' => true, 'form' => $form->getAttributes(), - 'questions' => [['question'=>'Question 1','answer'=>'Answer 1 will be here...']] + 'questions' => [['question' => 'Question 1', 'answer' => 'Answer 1 will be here...']], ]; $this->postJson(route('templates.create', $templateData)) ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Template was created.' + 'message' => 'Template was created.', ]); }); diff --git a/tests/Feature/VerificationTest.php b/tests/Feature/VerificationTest.php index d1a0036..7c82a25 100644 --- a/tests/Feature/VerificationTest.php +++ b/tests/Feature/VerificationTest.php @@ -1,12 +1,9 @@ create(['email_verified_at' => null]); diff --git a/tests/Feature/WorkspaceTest.php b/tests/Feature/WorkspaceTest.php index 6bfd1b1..63054f8 100644 --- a/tests/Feature/WorkspaceTest.php +++ b/tests/Feature/WorkspaceTest.php @@ -3,31 +3,31 @@ it('can create and delete Workspace', function () { $user = $this->actingAsUser(); - for($i=1;$i<=3;$i++){ + for ($i = 1; $i <= 3; $i++) { $this->postJson(route('open.workspaces.create'), [ - 'name' => 'Workspace Test - '.$i, - 'icon' => '๐Ÿงช', - ]) + 'name' => 'Workspace Test - '.$i, + 'icon' => '๐Ÿงช', + ]) ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Workspace created.' + 'message' => 'Workspace created.', ]); } expect($user->workspaces()->count())->toBe(3); - $i=0; - foreach($user->workspaces as $workspace){ + $i = 0; + foreach ($user->workspaces as $workspace) { $i++; - if($i !== 3){ + if ($i !== 3) { $this->deleteJson(route('open.workspaces.delete', $workspace->id)) ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Workspace deleted.' + 'message' => 'Workspace deleted.', ]); - }else{ + } else { // Last workspace can not delete $this->deleteJson(route('open.workspaces.delete', $workspace->id)) ->assertStatus(403); diff --git a/tests/Helpers/FormSubmissionDataFactory.php b/tests/Helpers/FormSubmissionDataFactory.php index ed8c668..c19ecf8 100644 --- a/tests/Helpers/FormSubmissionDataFactory.php +++ b/tests/Helpers/FormSubmissionDataFactory.php @@ -7,8 +7,7 @@ use Faker; class FormSubmissionDataFactory { - - private Faker\Generator|null $faker; + private ?Faker\Generator $faker; public function __construct(private Form $form) { @@ -68,24 +67,27 @@ class FormSubmissionDataFactory private function generateSelectValue($property) { $values = []; - if (isset($property["select"]["options"]) && count($property["select"]["options"]) > 0) { - $values = collect($property["select"]["options"])->map(function ($option) { + if (isset($property['select']['options']) && count($property['select']['options']) > 0) { + $values = collect($property['select']['options'])->map(function ($option) { return $option['name']; })->toArray(); } + return ($values) ? $this->faker->randomElement($values) : null; } private function generateMultiSelectValues($property) { $values = []; - if (isset($property["multi_select"]["options"]) && count($property["multi_select"]["options"]) > 0) { - $values = collect($property["multi_select"]["options"])->map(function ($option) { + if (isset($property['multi_select']['options']) && count($property['multi_select']['options']) > 0) { + $values = collect($property['multi_select']['options'])->map(function ($option) { return $option['name']; })->toArray(); } + return ($values) ? $this->faker->randomElements( $values, - $this->faker->numberBetween(1, count($values))) : null; + $this->faker->numberBetween(1, count($values)) + ) : null; } } diff --git a/tests/TestCase.php b/tests/TestCase.php index 44a35b4..6f91c23 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,14 +2,12 @@ namespace Tests; -use App\Models\User; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\TestCase as BaseTestCase; -use Illuminate\Support\Str; abstract class TestCase extends BaseTestCase { - use RefreshDatabase; use CreatesApplication; + use RefreshDatabase; use TestHelpers; } diff --git a/tests/TestHelpers.php b/tests/TestHelpers.php index 1156cf5..de94210 100644 --- a/tests/TestHelpers.php +++ b/tests/TestHelpers.php @@ -1,12 +1,10 @@ 'Form Testing', @@ -28,8 +27,8 @@ trait TestHelpers $user->workspaces()->sync([ $workspace->id => [ - 'role' => 'admin' - ] + 'role' => 'admin', + ], ], false); return $workspace; @@ -37,8 +36,7 @@ trait TestHelpers /** * Generates a Form instance (not saved) - * @param User $user - * @param Workspace $workspace + * * @return array */ public function makeForm(User $user, Workspace $workspace, array $data = []) @@ -48,20 +46,20 @@ trait TestHelpers 'name' => 'Name', 'type' => 'text', 'hidden' => false, - 'required' => false + 'required' => false, ], [ 'name' => 'Message', 'type' => 'text', 'hidden' => false, 'required' => false, - 'multi_lines' => true + 'multi_lines' => true, ], [ 'name' => 'Number', 'type' => 'number', 'hidden' => false, - 'required' => false + 'required' => false, ], [ 'name' => 'Select', @@ -70,8 +68,8 @@ trait TestHelpers 'required' => false, 'allow_creation' => false, 'select' => [ - 'options' => [['id' => 'First','name' => 'First'], ['id' => 'Second','name' => 'Second']] - ] + 'options' => [['id' => 'First', 'name' => 'First'], ['id' => 'Second', 'name' => 'Second']], + ], ], [ 'name' => 'Multi Select', @@ -80,45 +78,45 @@ trait TestHelpers 'required' => false, 'allow_creation' => false, 'multi_select' => [ - 'options' => [['id' => 'One','name' => 'One'], ['id' => 'Two','name' => 'Two'], ['id' => 'Three','name' => 'Three']] - ] + 'options' => [['id' => 'One', 'name' => 'One'], ['id' => 'Two', 'name' => 'Two'], ['id' => 'Three', 'name' => 'Three']], + ], ], [ 'name' => 'Date', 'type' => 'date', 'hidden' => false, - 'required' => false + 'required' => false, ], [ 'name' => 'Checkbox', 'type' => 'checkbox', 'hidden' => false, - 'required' => false + 'required' => false, ], [ 'name' => 'URL', 'type' => 'url', 'hidden' => false, - 'required' => false + 'required' => false, ], [ 'name' => 'Email', 'type' => 'email', 'hidden' => false, - 'required' => false + 'required' => false, ], [ 'name' => 'Phone Number', 'type' => 'phone_number', 'hidden' => false, - 'required' => false + 'required' => false, ], [ 'name' => 'Files', 'type' => 'files', 'hidden' => false, 'required' => false, - ] + ], ]; return Form::factory() @@ -132,6 +130,7 @@ trait TestHelpers { $form = $this->makeForm($user, $workspace, $data); $form->save(); + return $form; } @@ -155,7 +154,7 @@ trait TestHelpers return $user; } - public function actingAsUser(User $user = null) + public function actingAsUser(?User $user = null) { if ($user == null) { $user = $this->createUser(); @@ -172,10 +171,9 @@ trait TestHelpers /** * Creates a user with a Pro subscription * - * @param User|null $user * @return User|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model|null */ - public function actingAsProUser(User $user = null) + public function actingAsProUser(?User $user = null) { if ($user == null) { $user = $this->createProUser(); @@ -191,5 +189,4 @@ trait TestHelpers } $this->assertGuest(); } - } diff --git a/tests/Unit/Service/Forms/FormLogicPropertyResolverTest.php b/tests/Unit/Service/Forms/FormLogicPropertyResolverTest.php index 841a768..5d7cdd7 100644 --- a/tests/Unit/Service/Forms/FormLogicPropertyResolverTest.php +++ b/tests/Unit/Service/Forms/FormLogicPropertyResolverTest.php @@ -1,4 +1,5 @@ with([ [ [ - 'id' => "title", - 'name' => "Name", + 'id' => 'title', + 'name' => 'Name', 'type' => 'text', 'hidden' => false, 'required' => true, 'logic' => [ - "conditions" => [ - "operatorIdentifier"=> "and", - "children"=> [ + 'conditions' => [ + 'operatorIdentifier' => 'and', + 'children' => [ [ - "identifier"=> "user", - "value"=> [ - "operator"=> "is_not_empty", - "property_meta"=> [ - 'id'=> "93ea3198-353f-440b-8dc9-2ac9a7bee124", - "type"=> "select", + 'identifier' => 'user', + 'value' => [ + 'operator' => 'is_not_empty', + 'property_meta' => [ + 'id' => '93ea3198-353f-440b-8dc9-2ac9a7bee124', + 'type' => 'select', ], - "value"=> true - ] - ] - ] + 'value' => true, + ], + ], + ], ], - "actions" => ['make-it-optional'] - ] + 'actions' => ['make-it-optional'], + ], ], - ['93ea3198-353f-440b-8dc9-2ac9a7bee124'=>["One"]], - false + ['93ea3198-353f-440b-8dc9-2ac9a7bee124' => ['One']], + false, ], [ [ - 'id' => "title", - 'name' => "Name", + 'id' => 'title', + 'name' => 'Name', 'type' => 'text', 'hidden' => false, 'required' => true, 'logic' => [ - "conditions" => [ - "operatorIdentifier"=> "and", - "children"=> [ + 'conditions' => [ + 'operatorIdentifier' => 'and', + 'children' => [ [ - "identifier"=> "user", - "value"=> [ - "operator"=> "is_not_empty", - "property_meta"=> [ - 'id'=> "93ea3198-353f-440b-8dc9-2ac9a7bee124", - "type"=> "select", + 'identifier' => 'user', + 'value' => [ + 'operator' => 'is_not_empty', + 'property_meta' => [ + 'id' => '93ea3198-353f-440b-8dc9-2ac9a7bee124', + 'type' => 'select', ], - "value"=> true - ] - ] - ] + 'value' => true, + ], + ], + ], ], - "actions" => ['make-it-optional'] - ] + 'actions' => ['make-it-optional'], + ], ], - ['93ea3198-353f-440b-8dc9-2ac9a7bee124'=>[]], - true + ['93ea3198-353f-440b-8dc9-2ac9a7bee124' => []], + true, ], [ [ - 'id' => "title", - 'name' => "Name", + 'id' => 'title', + 'name' => 'Name', 'type' => 'text', 'hidden' => false, 'required' => true, 'logic' => [ - "conditions" => [ - "operatorIdentifier"=> "or", - "children"=> [ + 'conditions' => [ + 'operatorIdentifier' => 'or', + 'children' => [ [ - "identifier"=> "user", - "value"=> [ - "operator"=> "is_not_empty", - "property_meta"=> [ - 'id'=> "93ea3198-353f-440b-8dc9-2ac9a7bee124", - "type"=> "select", + 'identifier' => 'user', + 'value' => [ + 'operator' => 'is_not_empty', + 'property_meta' => [ + 'id' => '93ea3198-353f-440b-8dc9-2ac9a7bee124', + 'type' => 'select', ], - "value"=> true - ] + 'value' => true, + ], ], [ - "identifier"=> "email", - "value"=> [ - "operator"=> "contains", - "property_meta"=> [ - 'id'=> "93ea3198-353f-440b-8dc9-2ac9a7bee222", - "type"=> "email", + 'identifier' => 'email', + 'value' => [ + 'operator' => 'contains', + 'property_meta' => [ + 'id' => '93ea3198-353f-440b-8dc9-2ac9a7bee222', + 'type' => 'email', ], - "value"=> "abc" - ] - ] - ] + 'value' => 'abc', + ], + ], + ], ], - "actions" => ['make-it-optional'] - ] + 'actions' => ['make-it-optional'], + ], ], - ['93ea3198-353f-440b-8dc9-2ac9a7bee124'=>[], '93ea3198-353f-440b-8dc9-2ac9a7bee222'=>['abc']], - false - ] -]); \ No newline at end of file + ['93ea3198-353f-440b-8dc9-2ac9a7bee124' => [], '93ea3198-353f-440b-8dc9-2ac9a7bee222' => ['abc']], + false, + ], +]); diff --git a/tests/Unit/Service/Storage/StorageFileNameParserTest.php b/tests/Unit/Service/Storage/StorageFileNameParserTest.php index 71123d1..d008b7b 100644 --- a/tests/Unit/Service/Storage/StorageFileNameParserTest.php +++ b/tests/Unit/Service/Storage/StorageFileNameParserTest.php @@ -2,7 +2,7 @@ uses(\Tests\TestCase::class); -use \Illuminate\Support\Str; +use Illuminate\Support\Str; it('can parse filenames', function () { $fileName = 'Notion_app_logo_85e16d7b-58ed-43bc-8dce-7d3ff7d69f41.png'; diff --git a/tests/Unit/TestHelpersTest.php b/tests/Unit/TestHelpersTest.php index 982efa8..d8b7154 100644 --- a/tests/Unit/TestHelpersTest.php +++ b/tests/Unit/TestHelpersTest.php @@ -2,9 +2,6 @@ uses(\Tests\TestCase::class); -use function Pest\Faker\faker; -use Tests\Helpers\FormSubmissionDataFactory; - it('can create pro user who are subscribed', function () { $user = $this->actingAsProUser(); expect($user->is_subscribed)->toBeTrue(); @@ -19,7 +16,7 @@ it('can create test workspace', function () { it('can make a form for a database', function () { $user = $this->actingAsProUser(); $workspace = $this->createUserWorkspace($user); - $form = $this->makeForm($user,$workspace); + $form = $this->makeForm($user, $workspace); expect($form->title)->not()->toBeNull(); expect($form->description)->not()->toBeNull(); expect(count($form->properties))->not()->toBe(0);