json() : $data); $builder = build($this); $propertyAttributes = collect((new \ReflectionClass($this))->getProperties())->mapWithKeys(function ($property) { $property->setAccessible(true); return [$property->getName() => collect($property->getAttributes())->mapWithKeys(fn ($attr) => [$attr->getName() => $attr->getArguments()])]; })->all(); $propertyAttributes = Arr::dot($propertyAttributes); foreach ($data as $placement => $value) { $propertyPath = explode('.', Str::beforeLast($placement, '.')); $propertyName = array_shift($propertyPath); if ( ($propKey = array_search($placement, $propertyAttributes)) && Str::afterLast($propKey, '.') == 'Map' ) { $propertyPath = explode('.', Str::beforeLast($propKey, '.')); $propertyName = array_shift($propertyPath); } $placement = implode('.', array_filter([$propertyName, ...$propertyPath])); $attributes = array_filter( $propertyAttributes, fn ($key) => Str::beforeLast('.', $key) == $placement && Str::afterLast('.', $key) !== 'Map', ARRAY_FILTER_USE_KEY ); foreach ($attributes as $key => $attrValue) { $attrName = Str::afterLast($key, '.'); $value = $this->{Str::camel($attrName)}(params: $attrValue, value: $value); } $builder->set($placement, $value); } } /** * Validates values. * * @param string[] $params validations rules to apply to the value * * @todo Implement. May use illuminate/validation later on. * * @see https://github.com/mattstauffer/Torch/tree/master/components/validation **/ private function validate(array $params, mixed $value): mixed { return $value; } /** * Gets the DTO data as multidimensional an array **/ public function toArray(): array { $props = get_class_vars($this::class); unset($props['data']); return collect($props)->map(fn ($defaultVal, $key) => $this->{$key} ?? $defaultVal)->all(); } /** * Gets the DTO data as multidimensional an array **/ public function all(): array { return $this->toArray(); } }