false, 'color' => '#3B82F6', 'hide_title' => false, 'no_branding' => false, 'transparent_background' => false, 'uppercase_labels' => true, 'webhook_url' => null, 'cover_picture' => null, 'logo_picture' => null, 'database_fields_update' => null, 'theme' => 'default', 'use_captcha' => false, 'password' => null, 'slack_webhook_url' => null, 'discord_webhook_url' => null, ]; private array $fieldDefaults = [ // 'name' => '' TODO: prevent name changing, use alias for column and keep original name as it is 'hide_field_name' => false, 'prefill' => null, 'placeholder' => null, 'help' => null, 'file_upload' => false, 'with_time' => null, 'width' => 'full', 'generates_uuid' => false, 'generates_auto_increment_id' => false, 'logic' => null, 'allow_creation' => false ]; private array $cleaningMessages = [ // For form 'notifies' => "Email notification were disabled.", 'color' => "Form color set to default blue.", 'hide_title' => "Title is not hidden.", 'no_branding' => "OpenForm branding is not hidden.", 'transparent_background' => "Transparent background was disabled.", 'uppercase_labels' => "Labels use uppercase letters", 'webhook_url' => "Webhook disabled.", 'cover_picture' => 'The cover picture was removed.', 'logo_picture' => 'The logo was removed.', 'database_fields_update' => 'Form submission will only create new records (no updates).', 'theme' => 'Default theme was applied.', 'slack_webhook_url' => "Slack webhook disabled.", 'discord_webhook_url' => "Discord webhook disabled.", // For fields 'hide_field_name' => 'Hide field name removed.', 'prefill' => "Field prefill removed.", 'placeholder' => "Empty text (placeholder) removed", 'help' => "Help text removed.", 'file_upload' => "Link field is not a file upload.", 'with_time' => "Time was removed from date input.", 'custom_block' => 'The custom block was removed.', 'files' => 'The file upload file was hidden.', 'relation' => 'The relation file was hidden.', 'width' => 'The field width was set to full width', 'allow_creation' => 'Select option creation was disabled.', // Advanced fields 'generates_uuid' => 'ID generation disabled.', 'generates_auto_increment_id' => 'ID generation disabled.', 'use_captcha' => 'Captcha form protection was disabled.', // Security & Privacy 'password' => 'Password protection was disabled', 'logic' => 'Logic disabled for this property' ]; /** * Returns form data after request ingestion * @return array */ public function getData(): array { return $this->data; } /** * Returns true if at least one cleaning was done * @return bool */ public function hasCleaned(): bool { return count($this->cleanings) > 0; } /** * Returns the messages for each cleaning step performed */ public function getPerformedCleanings(): array { $cleaningMsgs = []; foreach ($this->cleanings as $key => $val) { $cleaningMsgs[$key] = collect($val)->map(function ($cleaning) { return $this->cleaningMessages[$cleaning]; }); } return $cleaningMsgs; } /** * Removes form pro features from data if user isn't pro */ public function processRequest(UserFormRequest $request): FormCleaner { $data = $request->validated(); $this->data = $this->commonCleaning($data); return $this; } /** * Create form cleaner instance from existing form */ public function processForm(Request $request, Form $form) : FormCleaner { $data = (new FormResource($form))->toArray($request); $this->data = $this->commonCleaning($data); return $this; } private function isPro(Workspace $workspace) { return $workspace->is_pro; } /** * Dry run celanings * @param User|null $user */ public function simulateCleaning(Workspace $workspace): FormCleaner { if($this->isPro($workspace)) return $this; $this->data = $this->removeProFeatures($this->data, true); return $this; } /** * Perform Cleanigns * @param User|null $user * @return $this|array */ public function performCleaning(Workspace $workspace): FormCleaner { if($this->isPro($workspace)) return $this; $this->data = $this->removeProFeatures($this->data); return $this; } /** * Clean all forms: * - Escape html of custom text block */ private function commonCleaning(array $data) { foreach ($data['properties'] as &$property) { if ($property['type'] == 'nf-text' && isset($property['content'])) { $property['content'] = Purify::clean($property['content']); } } return $data; } private function removeProFeatures(array $data, $simulation = false) { $this->cleanForm($data, $simulation); $this->cleanProperties($data, $simulation); return $data; } private function cleanForm(array &$data, $simulation = false): void { $this->clean($data, $this->formDefaults, $simulation); } private function cleanProperties(array &$data, $simulation = false): void { foreach ($data['properties'] as $key => &$property) { // Remove pro custom blocks if (\Str::of($property['type'])->startsWith('nf-')) { $this->cleanings[$property['name']][] = 'custom_block'; if (!$simulation) { unset($data['properties'][$key]); } continue; } // Clean pro field options $this->cleanField($property, $this->fieldDefaults, $simulation); } } private function clean(array &$data, array $defaults, $simulation = false): void { foreach ($defaults as $key => $value) { if (Arr::get($data, $key) !== $value) { if (!isset($this->cleanings['form'])) $this->cleanings['form'] = []; $this->cleanings['form'][] = $key; // If not a simulation, do the cleaning if (!$simulation) { Arr::set($data, $key, $value); } } } } private function cleanField(array &$data, array $defaults, $simulation = false): void { foreach ($defaults as $key => $value) { if (isset($data[$key]) && Arr::get($data, $key) !== $value) { $this->cleanings[$data['name']][] = $key; if (!$simulation) { Arr::set($data, $key, $value); } } } // Remove pro types columns foreach (['files'] as $proType) { if ($data['type'] == $proType && (!isset($data['hidden']) || !$data['hidden'])) { $this->cleanings[$data['name']][] = $proType; if (!$simulation) { $data['hidden'] = true; } } } } }