getObjectManager(); if (!$em instanceof EntityManagerInterface) { return; } $uow = $em->getUnitOfWork(); $actorProfileId = $this->resolveActorProfileId(); $pendingUpdates = []; $pendingSnapshots = []; $pendingPieces = []; foreach ($uow->getScheduledEntityInsertions() as $entity) { if (!$entity instanceof Piece) { continue; } $diff = $this->buildDiffFromChangeSet($uow->getEntityChangeSet($entity)); $snapshot = $this->snapshotPiece($entity); $this->persistAuditLog($em, new AuditLog('piece', (string) $entity->getId(), 'create', $diff, $snapshot, $actorProfileId)); } foreach ($uow->getScheduledEntityUpdates() as $entity) { if (!$entity instanceof Piece) { continue; } $pieceId = (string) $entity->getId(); if ($pieceId === '') { continue; } $diff = $this->buildDiffFromChangeSet($uow->getEntityChangeSet($entity)); if ($diff !== []) { $pendingUpdates[$pieceId] = $this->mergeDiffs($pendingUpdates[$pieceId] ?? [], $diff); $pendingSnapshots[$pieceId] = $this->snapshotPiece($entity); $pendingPieces[$pieceId] = $entity; } } foreach ($uow->getScheduledEntityDeletions() as $entity) { if (!$entity instanceof Piece) { continue; } $snapshot = $this->snapshotPiece($entity); $this->persistAuditLog($em, new AuditLog('piece', (string) $entity->getId(), 'delete', null, $snapshot, $actorProfileId)); } foreach ($uow->getScheduledCollectionUpdates() as $collection) { $this->collectCollectionUpdate($collection, $pendingUpdates, $pendingSnapshots, $pendingPieces); } foreach ($uow->getScheduledCollectionDeletions() as $collection) { $this->collectCollectionUpdate($collection, $pendingUpdates, $pendingSnapshots, $pendingPieces); } foreach ($pendingUpdates as $pieceId => $diff) { if ($diff === []) { continue; } $piece = $pendingPieces[$pieceId] ?? null; if (!$piece instanceof Piece) { continue; } $snapshot = $pendingSnapshots[$pieceId] ?? $this->snapshotPiece($piece); $this->persistAuditLog($em, new AuditLog('piece', $pieceId, 'update', $diff, $snapshot, $actorProfileId)); } } /** * @param array> $pendingUpdates * @param array> $pendingSnapshots * @param array $pendingPieces */ private function collectCollectionUpdate( object $collection, array &$pendingUpdates, array &$pendingSnapshots, array &$pendingPieces, ): void { if (!$collection instanceof PersistentCollection) { return; } $owner = $collection->getOwner(); if (!$owner instanceof Piece) { return; } $pieceId = (string) $owner->getId(); if ($pieceId === '') { 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[$pieceId] = $this->mergeDiffs($pendingUpdates[$pieceId] ?? [], $diff); $pendingSnapshots[$pieceId] = $this->snapshotPiece($owner); $pendingPieces[$pieceId] = $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 snapshotPiece(Piece $piece): array { return [ 'id' => $piece->getId(), 'name' => $piece->getName(), 'reference' => $piece->getReference(), 'prix' => $piece->getPrix(), 'typePiece' => $this->normalizeValue($piece->getTypePiece()), 'product' => $this->normalizeValue($piece->getProduct()), 'productIds' => $piece->getProductIds(), 'constructeurIds' => $this->normalizeCollection($piece->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; } }