merge([ 'contacts' => \collect($this->contacts)->filter() ->map(function ($contact) { $contact = \collect($contact); if ($contact->has('data')) { $contact->put('data', \collect($contact->get('data'))->all()); $contact->put('dataParsed', \collect($contact->get('data')) ->map(function ($value, $index) { return \call_user_func([$this, 'filterDataLine'], \collect($value)->all(), $index); }) ->filter()->all()); } if ($contact->has('visits')) { $contact->put('visits', \collect($contact->get('visits'))->filter() ->map(function ($visit) { if (!\is_array($visit)) { return $visit; } $visit = \collect($visit); $visit->put('note', $visit->get('note') ?? ''); return $visit->all(); })->all()); } return $contact->all(); })->all() ]); } /** * Get the validation rules that apply to the request. * * @return array */ public function rules(): array { return [ 'contacts' => 'present|array', 'contacts.*' => 'array', 'contacts.*.id' => 'uuid', 'contacts.*.lastname' => 'nullable|string|between:1,255', 'contacts.*.firstname' => 'nullable|string|between:1,255', // * Dot not validate email here (soft validate), if it does not pass, app will be blocked. 'contacts.*.email' => 'required|string|between:1,255', 'contacts.*.phone' => 'nullable|string|between:1,255', 'contacts.*.timestamp' => 'required|date', // * DATA 'contacts.*.data' => 'present|array', 'contacts.*.dataParsed' => 'present', 'contacts.*.data.*' => 'array', 'contacts.*.data.*.title' => 'present|string|min:1|max:255', 'contacts.*.data.*.formSlug' => 'present|string|min:1|max:255', 'contacts.*.data.*.type' => ['present', new Enum(InputTypeEnum::class)], 'contacts.*.data.*.value' => 'present', 'contacts.*.data.*.required' => 'present|boolean', 'contacts.*.data.*.send_to_app_user_id' => 'nullable|numeric', 'contacts.*.notes' => 'nullable|string', 'contacts.*.visits' => 'present|array', 'contacts.*.visits.*' => 'required|array', 'contacts.*.visits.*.title' => 'present|string', 'contacts.*.visits.*.note' => 'present|string', ]; } /** * Handle a line of data (input) * * @param array $data * @param mixed $index * @return mixed * @throws \Illuminate\Validation\ValidationException In case of parse failure. */ private function filterDataLine(array $data, mixed $index): mixed { $data = \collect($data); try { $title = $data->get('title') ? \strval($data->get('title')) : null; if (\is_null($title)) { throw ValidationException::withMessages([ 'error' => "wrong title on data index '{$index}'" ]); } $formSlug = $data->get('formSlug') ? \strval($data->get('formSlug')) : null; if (\is_null($formSlug)) { throw ValidationException::withMessages([ 'error' => "wrong formSlug on data index '{$index}'" ]); } $type = InputTypeEnum::make($data->get('type') ? $data->get('type') : null); if (\is_null($type)) { throw ValidationException::withMessages([ 'error' => "wrong inputType on data index '{$index}'" ]); } $value = $data['value'] ?? null; $required = $data->get('required') ? true : false; $inputClass = $type->getInputClass(); return $inputClass::from(InputData::make( $title, $formSlug, $type, $value, $required ), $required); } catch (\TypeError | \BadMethodCallException $e) { throw ValidationException::withMessages([ 'error' => "wrong type on data index '{$index}'" ]); } catch (\RuntimeException $e) { $message = $e->getMessage(); throw ValidationException::withMessages([ 'error' => "wrong data on index '{$index}' '{$message}'" ]); } //end try } }