diff --git a/CHANGELOG.md b/CHANGELOG.md index 91b7ab6..65cfc80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [2.9.0] - 2024-09-10 +### Added +- `processValues()` now allows setting the ID of an existing row on the returned object, in which +case a new row will not be inserted, and the specified ID will be returned in the list of row IDs. ## [2.8.0] - 2023-12-22 ### Added @@ -151,7 +154,7 @@ return early if passed an empty IDs array. ### Changed - Initial stable release -[Unreleased]: https://github.com/theodorejb/phaster/compare/v2.8.0...HEAD +[2.9.0]: https://github.com/theodorejb/phaster/compare/v2.8.0...v2.9.0 [2.8.0]: https://github.com/theodorejb/phaster/compare/v2.7.0...v2.8.0 [2.7.0]: https://github.com/theodorejb/phaster/compare/v2.6.0...v2.7.0 [2.6.0]: https://github.com/theodorejb/phaster/compare/v2.5.0...v2.6.0 diff --git a/src/Entities.php b/src/Entities.php index 31cda30..9f2f792 100644 --- a/src/Entities.php +++ b/src/Entities.php @@ -263,15 +263,32 @@ public function addEntities(array $entities): array $defaultValues = $this->getDefaultValues(); $rows = []; - - foreach ($entities as $entity) { - $data = array_replace_recursive($defaultValues, $entity); - $row = Helpers::allPropertiesToColumns($this->map, $this->processValues($data, [])); - $rows[] = $this->processRow($row, []); + $existingIds = []; + + foreach ($entities as $key => $entity) { + unset($entity[$this->idField]); // any ID posted to API should be ignored + $entity = array_replace_recursive($defaultValues, $entity); + $entity = $this->processValues($entity, []); + + // if processValues sets an ID for an existing item, don't insert a new row for it + if (isset($entity[$this->idField])) { + $id = $entity[$this->idField]; + if (!is_int($id)) { + throw new \Exception('ID value set by processValues must be an integer'); + } + $existingIds[$key] = $id; + } else { + $row = Helpers::allPropertiesToColumns($this->map, $entity); + $rows[] = $this->processRow($row, []); + } } try { - return $this->db->insertRows($this->getTableName(), $rows, $this->getIdentityIncrement())->getIds(); + $ids = $this->db->insertRows($this->getTableName(), $rows, $this->getIdentityIncrement())->getIds(); + foreach ($existingIds as $offset => $id) { + array_splice($ids, $offset, 0, [$id]); + } + return $ids; } catch (SqlException $e) { throw $this->properException($e); } diff --git a/test/EntitiesDbTest.php b/test/EntitiesDbTest.php index ff3da39..cd8afe4 100644 --- a/test/EntitiesDbTest.php +++ b/test/EntitiesDbTest.php @@ -362,6 +362,8 @@ public function testModernUsers(Entities $entities, PeachySql $db): void } $ids = $entities->addEntities($users); + $this->assertSame(-42, $ids[1]); // manually set ID in processValues + $db->insertRow('UserThings', ['user_id' => $ids[3]]); $actual = $entities->getEntitiesByIds([$ids[2], $ids[3]], ['id', 'name', 'isDisabled', 'computed', 'weight', 'thing.uid']); diff --git a/test/src/ModernUsers.php b/test/src/ModernUsers.php index 3e82ace..6889330 100644 --- a/test/src/ModernUsers.php +++ b/test/src/ModernUsers.php @@ -59,8 +59,12 @@ protected function getBaseQuery(QueryOptions $options): string protected function processValues(array $data, array $ids): array { - if (count($ids) === 0 && $data['name'] === 'Modern user 3') { - $data['name'] = 'Modern user 3 modified'; + if (count($ids) === 0) { + if ($data['name'] === 'Modern user 3') { + $data['name'] = 'Modern user 3 modified'; + } elseif ($data['name'] === 'Modern user 2') { + $data['id'] = -42; // don't insert row for this item + } } return $data;