$values * @return array */ public function validate(array $values): array { abort_unless(config('portal.opportunity_specialized_drafts_enabled'), 422, 'Campos especializados ainda não disponibilizados neste ambiente.'); $bytes = file_get_contents(resource_path('data/investmoz-opportunity-modular.schema.json')); if ($bytes === false) { throw new \RuntimeException('Normative opportunity schema unavailable.'); } $schema = json_decode($bytes, true, 512, JSON_THROW_ON_ERROR); $properties = $schema['$defs']['realEstatePatch']['properties']; if ($values === [] || array_diff(array_keys($values), array_keys($properties))) { throw ValidationException::withMessages(['real_estate' => 'Indique campos do contrato imobiliário; campos desconhecidos ou de resposta não são graváveis.']); } $errors = []; foreach ($values as $key => $value) { $this->check($value, $properties[$key], 'real_estate.'.$key, $errors); } if ($errors) { throw ValidationException::withMessages($errors); } return $values; } /** * @param array $schema * @param array $errors */ private function check(mixed $value, array $schema, string $path, array &$errors): void { $types = (array) ($schema['type'] ?? []); $valid = $types === [] || array_filter($types, fn ($type) => match ($type) { 'null' => $value === null, 'string' => is_string($value), 'integer' => is_int($value), 'number' => is_int($value) || is_float($value), 'boolean' => is_bool($value), 'array' => is_array($value) && array_is_list($value), // Laravel request arrays represent JSON objects, including empty ones. 'object' => is_array($value) && ($value === [] || ! array_is_list($value)), default => false, }) !== []; if (! $valid || (isset($schema['enum']) && ! in_array($value, $schema['enum'], true))) { $errors[$path] = 'Tipo ou valor fora do contrato imobiliário §26.'; return; } if ($value === null) { return; } $rules = []; foreach (['minLength' => 'min', 'maxLength' => 'max', 'minItems' => 'min'] as $keyword => $rule) { if (isset($schema[$keyword])) { $rules[] = $rule.':'.$schema[$keyword]; } } if (in_array('number', $types, true) || in_array('integer', $types, true)) { $rules[] = 'numeric'; foreach (['minimum' => 'min', 'maximum' => 'max', 'exclusiveMinimum' => 'gt'] as $keyword => $rule) { if (isset($schema[$keyword])) { $rules[] = $rule.':'.$schema[$keyword]; } } } if (($schema['format'] ?? null) === 'uuid') { $rules[] = 'uuid'; } if ($rules && Validator::make(['value' => $value], ['value' => $rules])->fails()) { $errors[$path] = 'Valor fora dos limites/formato do contrato imobiliário §26.'; } if (isset($schema['items']) && is_array($value)) { foreach ($value as $index => $item) { $this->check($item, $schema['items'], $path.'.'.$index, $errors); } } } }