Files
Mitgliederverwaltung/.plans/done/issue-204-duplicate-sync-methods.md
T
2026-04-30 08:13:11 +02:00

1.9 KiB

Issue #204: Duplicate Sub-Entity Sync Methods

Problem

MemberService contains three nearly identical methods for syncing sub-entities:

  • syncAddresses()
  • syncPhones()
  • syncEmails()

They all follow the same pattern:

  1. Fetch existing entities
  2. Index by ID
  3. Update kept IDs, create new ones
  4. Delete removed IDs

This violates DRY (Don't Repeat Yourself) and makes maintenance harder.

Current Code

private function syncAddresses(int $memberId, array $incoming): void {
    $existing = $this->addressMapper->findByMemberId($memberId);
    $existingById = [];
    foreach ($existing as $addr) {
        $existingById[$addr->getId()] = $addr;
    }
    $keptIds = [];
    foreach ($incoming as $item) {
        $id = isset($item['id']) ? (int)$item['id'] : 0;
        if ($id > 0 && isset($existingById[$id])) {
            $this->updateAddress($id, $item);
            $keptIds[$id] = true;
        } else {
            $this->addAddress($memberId, $item);
        }
    }
    foreach ($existingById as $id => $addr) {
        if (!isset($keptIds[$id])) {
            $this->deleteAddress($id);
        }
    }
}
// syncPhones() and syncEmails() are identical except for Address → Phone/Email

Solution

Extract the common sync logic into a single private generic method that accepts callables for the mapper-specific operations. Each of the three sync methods becomes a thin 10-line wrapper calling the generic method.

Tasks

  • Extract common sync logic into syncSubEntities() private generic method
  • Refactor syncAddresses(), syncPhones(), syncEmails() to use the new pattern
  • Ensure identical behavior is preserved (all existing tests must pass)
  • Run make test — all must pass
  • Commit, push, create PR via tea, merge it
  • Move plan file from .plans/open/ to .plans/done/
  • Check out main again

Labels

  • refactoring
  • backend
  • priority:medium