getObjectManager(); if (!$em instanceof EntityManagerInterface) { return; } $uow = $em->getUnitOfWork(); $actorProfileId = $this->resolveActorProfileId(); $pendingUpdates = []; $pendingSnapshots = []; $pendingComponents = []; foreach ($uow->getScheduledEntityInsertions() as $entity) { if (!$entity instanceof Composant) { continue; } $diff = $this->buildDiffFromChangeSet($uow->getEntityChangeSet($entity)); $snapshot = $this->snapshotComposant($entity); $this->persistAuditLog($em, new AuditLog('composant', (string) $entity->getId(), 'create', $diff, $snapshot, $actorProfileId)); } foreach ($uow->getScheduledEntityUpdates() as $entity) { if (!$entity instanceof Composant) { continue; } $componentId = (string) $entity->getId(); if ($componentId === '') { continue; } $diff = $this->buildDiffFromChangeSet($uow->getEntityChangeSet($entity)); if ($diff !== []) { $pendingUpdates[$componentId] = $this->mergeDiffs($pendingUpdates[$componentId] ?? [], $diff); $pendingSnapshots[$componentId] = $this->snapshotComposant($entity); $pendingComponents[$componentId] = $entity; } } foreach ($uow->getScheduledEntityDeletions() as $entity) { if (!$entity instanceof Composant) { continue; } $snapshot = $this->snapshotComposant($entity); $this->persistAuditLog($em, new AuditLog('composant', (string) $entity->getId(), 'delete', null, $snapshot, $actorProfileId)); } foreach ($uow->getScheduledCollectionUpdates() as $collection) { $this->collectCollectionUpdate($collection, $pendingUpdates, $pendingSnapshots, $pendingComponents); } foreach ($uow->getScheduledCollectionDeletions() as $collection) { $this->collectCollectionUpdate($collection, $pendingUpdates, $pendingSnapshots, $pendingComponents); } foreach ($pendingUpdates as $componentId => $diff) { if ($diff === []) { continue; } $component = $pendingComponents[$componentId] ?? null; if (!$component instanceof Composant) { continue; } $snapshot = $pendingSnapshots[$componentId] ?? $this->snapshotComposant($component); $this->persistAuditLog($em, new AuditLog('composant', $componentId, 'update', $diff, $snapshot, $actorProfileId)); } } /** * @param array> $pendingUpdates * @param array> $pendingSnapshots * @param array $pendingComponents */ private function collectCollectionUpdate( object $collection, array &$pendingUpdates, array &$pendingSnapshots, array &$pendingComponents, ): void { if (!$collection instanceof PersistentCollection) { return; } $owner = $collection->getOwner(); if (!$owner instanceof Composant) { return; } $componentId = (string) $owner->getId(); if ($componentId === '') { return; } $mapping = $collection->getMapping(); $fieldName = $mapping['fieldName'] ?? null; if ($fieldName !== 'constructeurs') { return; } $before = $this->normalizeCollection($collection->getSnapshot()); $after = $this->normalizeCollection($collection->toArray()); if ($before === $after) { return; } $diff = [ 'constructeurIds' => [ 'from' => $before, 'to' => $after, ], ]; $pendingUpdates[$componentId] = $this->mergeDiffs($pendingUpdates[$componentId] ?? [], $diff); $pendingSnapshots[$componentId] = $this->snapshotComposant($owner); $pendingComponents[$componentId] = $owner; } private function persistAuditLog(EntityManagerInterface $em, AuditLog $log): void { $uow = $em->getUnitOfWork(); $log->initializeAuditLog(); $em->persist($log); $meta = $em->getClassMetadata(AuditLog::class); $uow->computeChangeSet($meta, $log); } /** * @param array $changeSet * @return array */ private function buildDiffFromChangeSet(array $changeSet): array { $diff = []; foreach ($changeSet as $field => [$oldValue, $newValue]) { if ($field === 'updatedAt' || $field === 'createdAt') { continue; } $normalizedOld = $this->normalizeValue($oldValue); $normalizedNew = $this->normalizeValue($newValue); if ($normalizedOld === $normalizedNew) { continue; } $diff[$field] = [ 'from' => $normalizedOld, 'to' => $normalizedNew, ]; } return $diff; } private function snapshotComposant(Composant $component): array { return [ 'id' => $component->getId(), 'name' => $component->getName(), 'reference' => $component->getReference(), 'prix' => $component->getPrix(), 'structure' => $component->getStructure(), 'typeComposant' => $this->normalizeValue($component->getTypeComposant()), 'product' => $this->normalizeValue($component->getProduct()), 'constructeurIds' => $this->normalizeCollection($component->getConstructeurs()), ]; } /** * @param iterable $items * @return list */ private function normalizeCollection(iterable $items): array { $ids = []; foreach ($items as $item) { if (\is_object($item) && \method_exists($item, 'getId')) { $id = $item->getId(); if ($id !== null && $id !== '') { $ids[] = (string) $id; } } } sort($ids); return array_values(array_unique($ids)); } private function normalizeValue(mixed $value): mixed { if ($value === null || \is_scalar($value)) { return $value; } if ($value instanceof \DateTimeInterface) { return $value->format(\DateTimeInterface::ATOM); } if ($value instanceof ModelType) { return [ 'id' => $value->getId(), 'name' => $value->getName(), 'code' => $value->getCode(), ]; } if ($value instanceof Product) { return [ 'id' => $value->getId(), 'name' => $value->getName(), 'reference' => $value->getReference(), ]; } if ($value instanceof Collection) { return $this->normalizeCollection($value); } if (\is_object($value) && \method_exists($value, 'getId')) { return (string) $value->getId(); } if (\is_array($value)) { return $value; } return (string) $value; } /** * @param array $base * @param array $extra * @return array */ private function mergeDiffs(array $base, array $extra): array { foreach ($extra as $field => $change) { $base[$field] = $change; } return $base; } private function resolveActorProfileId(): ?string { $session = $this->requestStack->getSession(); if (!$session instanceof SessionInterface) { return null; } $profileId = $session->get('profileId'); if (!$profileId) { return null; } return (string) $profileId; } }