diff --git a/src/Alias/Model/Mapping.php b/src/Alias/Model/Mapping.php new file mode 100644 index 0000000..28e478f --- /dev/null +++ b/src/Alias/Model/Mapping.php @@ -0,0 +1,63 @@ +input; + } + public function getOutputName(): string + { + return $this->output; + } + public function getTransformation(): callable + { + return $this->transformation; + } + + public function setInputName(string $input): \ProVM\Concept\Model\Mapping + { + $this->input = $input; + return $this; + } + public function setOutputName(string $output): \ProVM\Concept\Model\Mapping + { + $this->output = $output; + return $this; + } + public function setTransformation(callable $transformation): \ProVM\Concept\Model\Mapping + { + $this->transformation = $transformation; + return $this; + } + + public function __invoke(mixed $input, mixed &$output, ?array $params = null): void + { + if (is_array($input)) { + $input_value = $input[$this->getInputName()]; + } + if (is_a($input, Model::class)) { + $input_value = $input->{$this->getInputName()}(); + } + + $args = [$input_value]; + if ($params !== null) { + $args = array_merge($args, $params); + } + $output_value = call_user_func_array($this->getTransformation(), $args); + + if (is_array($output)) { + $output[$this->getOutputName()] = $output_value; + } + if (is_a($output, Model::class)) { + $output->{$this->getOutputName()}($output_value); + } + } +} \ No newline at end of file diff --git a/src/Alias/Model/Repository.php b/src/Alias/Model/Repository.php index 0ddede7..0c9a444 100644 --- a/src/Alias/Model/Repository.php +++ b/src/Alias/Model/Repository.php @@ -5,6 +5,7 @@ use ProVM\Concept\Database\Connection; use ProVM\Concept\Database\QueryBuilder; use ProVM\Concept\Model; use ProVM\Concept\Model\Factory; +use ProVM\Concept\Model\Mapping; use ProVM\Concept\Model\Repository as RepositoryInterface; abstract class Repository implements RepositoryInterface @@ -73,60 +74,40 @@ abstract class Repository implements RepositoryInterface { return $this->table; } - protected array $mappings; - public function getMappings(): array + protected array $column_mappings; + protected array $property_mappings; + public function getColumnMappings(): array { - if (isset($this->mappings)) { - return $this->mappings; - } - $mappings = []; - foreach ($this->getColumns() as $column) { - $mappings []= (object) ['column' => $column, 'property' => $column]; - } - return $mappings; + return $this->column_mappings; } - public function addMapping(string $column, string $property): Repository + public function addColumnMapping(Mapping $mapping): RepositoryInterface { - $this->mappings []= (object) compact('column', 'property'); + $this->column_mappings []= $mapping; return $this; } - public function setMappings(array $mappings): Repository + public function setColumnMappings(array $mappings): RepositoryInterface { foreach ($mappings as $mapping) { - if (is_array($mapping)) { - $this->addMapping($mapping['column'], $mapping['property']); - } - if (is_object($mapping)) { - $this->addMapping($mapping->column, $mapping->property); - } + $this->addColumnMapping($mapping); } return $this; } - public function findColumnByProperty(string $property): string + public function getPropertyMappings(): array { - foreach ($this->getMappings() as $mapping) { - if ($mapping->property === $property) { - return $mapping->column; - } - } - if (in_array($property, $this->getColumns())) { - return $property; - } - throw new \InvalidArgumentException("Property {$property} not found in mapping in " . get_called_class()); + return $this->property_mappings; } - public function findPropertyByColumn(string $column): string + public function addPropertyMapping(Mapping $mapping): Repository { - foreach ($this->getMappings() as $mapping) { - if ($mapping->column === $column) { - return $mapping->property; - } - } - if (in_array($column, $this->getProperties())) { - return $column; - } - throw new \InvalidArgumentException("Column {$column} not found in mapping in " . get_called_class()); + $this->property_mappings []= $mapping; + return $this; + } + public function setPropertyMappings(array $mappings): Repository + { + foreach ($mappings as $mapping) { + $this->addPropertyMapping($mapping); + } + return $this; } - protected array $columns; public function setColumns(array $columns): RepositoryInterface { @@ -220,52 +201,15 @@ abstract class Repository implements RepositoryInterface } public function fillData(Model $model, array $data): Model { - foreach ($this->getColumns() as $column) { - try { - $property = $this->findPropertyByColumn($column); - } catch (\InvalidArgumentException $e) { - continue; - } - $m = $this->getMethod($property, false); - if (!method_exists($model, $m)) { - continue; - } - $model->{$m}($data[$column]); - } - foreach ($this->getOptional() as $column) { - try { - $property = $this->findPropertyByColumn($column); - } catch (\InvalidArgumentException $e) { - continue; - } - $m = $this->getMethod($property, false); - if (!isset($data[$column])) { - continue; - } - if (!method_exists($model, $m)) { - continue; - } - $model->{$m}($data[$column]); + foreach ($this->getPropertyMappings() as $mapping) { + $mapping($data, $model); } return $model; } public function mapArray(Model $model, array $data): array { - foreach ($this->getProperties() as $property) { - try { - $column = $this->findColumnByProperty($property); - } catch (\InvalidArgumentException $e) { - continue; - } - if (isset($data[$column])) { - continue; - } - $m = $this->getMethod($property); - if (!method_exists($model, $m)) { - continue; - } - $val = $model->{$m}(); - $data[$column] = $val; + foreach ($this->getColumnMappings() as $mapping) { + $mapping($model, $data); } return $data; } @@ -283,7 +227,7 @@ abstract class Repository implements RepositoryInterface $this->update($model); return; } - $values = $this->mapArray($model, []); + $values = array_replace(array_flip($this->getColumns()), $this->mapArray($model, [])); $cols = array_fill(0, count($values), '?'); $query = $this->getQueryBuilder()->insert($this->getTable())->columns($this->getColumns())->values($cols); $this->getConnection()->execute($query, array_values($values)); diff --git a/src/Concept/Model/Mapping.php b/src/Concept/Model/Mapping.php new file mode 100644 index 0000000..15e19cf --- /dev/null +++ b/src/Concept/Model/Mapping.php @@ -0,0 +1,13 @@ +setInputName($input) + ->setOutputName($output) + ->setTransformation(function($item) { + return $item; + }); + } +} \ No newline at end of file