refactor(customfield): interface-based DI for repositories

Align CustomField-Schicht mit core/Repository/Access-Muster. Vier
Repositories (Tenant-Definition, Tenant-Option, User-Value, User-Value-Option)
bekommen je ein Interface, werden von static auf instance umgestellt und
ueber CustomFieldRepositoryFactory injiziert.

TenantCustomFieldService und UserCustomFieldValueService injizieren die
Repository-Interfaces statt statisch aufzurufen. CustomFieldServicesFactory
reicht Instanzen durch. AddressBookService (Modul) bekommt
TenantCustomFieldOptionRepositoryInterface per Container — Interface-Kopplung
verbessert Modul-Isolation gegenueber dem vorherigen statischen Aufruf.

Kein Verhaltenswechsel, keine SQL-Aenderung, keine Service-Signatur-Aenderung.
Alle tenant_id-Parameter erhalten (GR-SEC-009, Security-Review SR-002).

Oeffnet den Weg fuer Cluster B1 (TenantCustomFieldService-Tests) und B2
(UserCustomFieldValueService-Tests), die nun mit createMock() moeglich sind.

Nebenbei zwei PHPStan-Folge-Findings korrigiert:
- Veralteter Ignore-Eintrag fuer findById aus phpstan-baseline.neon entfernt
- Redundanter is_array-Check in TenantCustomFieldOptionRepository entfernt
  (durch typisierte Interface-Signatur abgedeckt)

Gates: QG-001 (1945 Tests, 28581 Assertions) / QG-002 / QG-003 / QG-006 pass.

Workflow: .agents/runs/CUSTOMFIELD-DI-REFACTOR-001/

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-22 19:32:14 +02:00
parent 0da785f4b7
commit 6b05bbfe9c
18 changed files with 227 additions and 83 deletions

View File

@@ -6,7 +6,7 @@ use MintyPHP\DB;
use MintyPHP\Repository\Support\RepoQuery;
/** Reads and writes tenant-scoped custom field definitions with type and pagination filtering. */
class TenantCustomFieldDefinitionRepository
class TenantCustomFieldDefinitionRepository implements TenantCustomFieldDefinitionRepositoryInterface
{
private static function unwrap(?array $row): ?array
{
@@ -31,7 +31,7 @@ class TenantCustomFieldDefinitionRepository
return $list;
}
public static function listByTenantId(int $tenantId, bool $onlyActive = true): array
public function listByTenantId(int $tenantId, bool $onlyActive = true): array
{
if ($tenantId <= 0) {
return [];
@@ -46,7 +46,7 @@ class TenantCustomFieldDefinitionRepository
return self::unwrapList(DB::select($query, ...$params));
}
public static function listByTenantIds(array $tenantIds, bool $onlyActive = true): array
public function listByTenantIds(array $tenantIds, bool $onlyActive = true): array
{
$tenantIds = array_values(array_unique(array_map('intval', $tenantIds)));
$tenantIds = array_values(array_filter($tenantIds, static fn ($id) => $id > 0));
@@ -63,7 +63,7 @@ class TenantCustomFieldDefinitionRepository
return self::unwrapList(call_user_func_array(['MintyPHP\\DB', 'select'], array_merge([$query], $params)));
}
public static function listFilterableByTenantIds(array $tenantIds): array
public function listFilterableByTenantIds(array $tenantIds): array
{
$tenantIds = array_values(array_unique(array_map('intval', $tenantIds)));
$tenantIds = array_values(array_filter($tenantIds, static fn ($id) => $id > 0));
@@ -78,7 +78,7 @@ class TenantCustomFieldDefinitionRepository
return self::unwrapList(call_user_func_array(['MintyPHP\\DB', 'select'], [$query, $tenantIds]));
}
public static function findByUuid(string $uuid): ?array
public function findByUuid(string $uuid): ?array
{
$row = DB::selectOne(
'select id, uuid, tenant_id, field_key, label, type, is_required, is_filterable, active, sort_order, created_by, modified_by, created, modified ' .
@@ -88,7 +88,7 @@ class TenantCustomFieldDefinitionRepository
return self::unwrap($row);
}
public static function findById(int $id): ?array
public function findById(int $id): ?array
{
$row = DB::selectOne(
'select id, uuid, tenant_id, field_key, label, type, is_required, is_filterable, active, sort_order, created_by, modified_by, created, modified ' .
@@ -98,7 +98,7 @@ class TenantCustomFieldDefinitionRepository
return self::unwrap($row);
}
public static function findByTenantIdAndKey(int $tenantId, string $fieldKey): ?array
public function findByTenantIdAndKey(int $tenantId, string $fieldKey): ?array
{
if ($tenantId <= 0 || $fieldKey === '') {
return null;
@@ -112,7 +112,7 @@ class TenantCustomFieldDefinitionRepository
return self::unwrap($row);
}
public static function create(array $data): int|false
public function create(array $data): int|false
{
return DB::insert(
'insert into tenant_custom_field_definitions ' .
@@ -131,7 +131,7 @@ class TenantCustomFieldDefinitionRepository
);
}
public static function update(int $id, array $data): bool
public function update(int $id, array $data): bool
{
if ($id <= 0) {
return false;
@@ -164,7 +164,7 @@ class TenantCustomFieldDefinitionRepository
return $result !== false;
}
public static function delete(int $id): bool
public function delete(int $id): bool
{
if ($id <= 0) {
return false;