Skip to content

Commit ca7901d

Browse files
author
Bjorn Van Acker
authored
Merge pull request #144 from sumocoders/294-automatic-logging-audit-trail
Add catches for circular references
2 parents 91b2c00 + a576373 commit ca7901d

File tree

3 files changed

+78
-5
lines changed

3 files changed

+78
-5
lines changed

src/DoctrineListener/DoctrineAuditListener.php

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
use SumoCoders\FrameworkCoreBundle\Attribute\AuditTrail\AuditTrailSensitiveData;
1818
use SumoCoders\FrameworkCoreBundle\Enum\EventAction;
1919
use SumoCoders\FrameworkCoreBundle\Logger\AuditLogger;
20+
use SumoCoders\FrameworkCoreBundle\Serializer\CircularReferenceHandler;
21+
use SumoCoders\FrameworkCoreBundle\Serializer\MaxDepthHandler;
22+
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
23+
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
2024
use Symfony\Component\Serializer\SerializerInterface;
2125

2226
#[AsDoctrineListener(event: Events::postPersist, priority: 500)]
@@ -55,7 +59,7 @@ public function preRemove(PreRemoveEventArgs $args): void
5559
{
5660
$entity = $args->getObject();
5761
$properties = $this->getProperties($entity);
58-
$data = $this->serializer->normalize($entity);
62+
$data = $this->serialize($entity);
5963

6064
// Hide sensitive data
6165
foreach ($properties as $property) {
@@ -118,7 +122,7 @@ private function log(object $entity, EventAction $action, EntityManagerInterface
118122

119123
break;
120124
case EventAction::CREATE:
121-
$entityData = $this->serializer->normalize($entity);
125+
$entityData = $this->serialize($entity);
122126
$entityFields = array_keys($entityData);
123127

124128
if (!$this->showDataForEntity($entity) && !$this->showPropertyDataForEntity($entity)) {
@@ -172,11 +176,24 @@ private function log(object $entity, EventAction $action, EntityManagerInterface
172176
);
173177
}
174178

179+
private function serialize(object $object): array
180+
{
181+
return $this->serializer->normalize(
182+
$object,
183+
null,
184+
[
185+
AbstractObjectNormalizer::ENABLE_MAX_DEPTH => true,
186+
AbstractObjectNormalizer::MAX_DEPTH_HANDLER => new MaxDepthHandler(),
187+
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => new CircularReferenceHandler(),
188+
]
189+
);
190+
}
191+
175192
private function getIdForEntity(object $entity): ?string
176193
{
177194
$properties = $this->getProperties($entity);
178195
$methods = $this->getMethods($entity);
179-
$serializedData = $this->serializer->normalize($entity);
196+
$serializedData = $this->serialize($entity);
180197

181198
foreach ($properties as $property) {
182199
if ($this->isPropertyPrimaryKey($entity, $property)) {
@@ -198,7 +215,7 @@ private function getIdentifierForEntity(object $entity): ?string
198215
// Check if the entity has a AuditTrailIdentifier::class attribute
199216
$properties = $this->getProperties($entity);
200217
$methods = $this->getMethods($entity);
201-
$serializedData = $this->serializer->normalize($entity);
218+
$serializedData = $this->serialize($entity);
202219

203220
foreach ($properties as $property) {
204221
if ($this->isPropertyIdentifier($entity, $property)) {
@@ -238,7 +255,7 @@ private function getDataForDeletedEntity(object $entity): ?array
238255
}
239256

240257
$idProperty = array_shift($properties);
241-
$serializedEntity = $this->serializer->normalize($entity);
258+
$serializedEntity = $this->serialize($entity);
242259

243260
foreach ($removals as $rKey => $removal) {
244261
$isSameEntity = true;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace SumoCoders\FrameworkCoreBundle\Serializer;
4+
5+
use Doctrine\ORM\Mapping\Id;
6+
7+
class CircularReferenceHandler
8+
{
9+
public function __invoke($object)
10+
{
11+
return $this->getId($object);
12+
}
13+
14+
private function getId(object $object): ?string
15+
{
16+
$reflectionClass = new \ReflectionClass($object);
17+
$properties = $reflectionClass->getProperties();
18+
19+
foreach ($properties as $property) {
20+
if ($property->getAttributes(Id::class)) {
21+
$property->setAccessible(true);
22+
return (string) $property->getValue($object);
23+
}
24+
}
25+
26+
return null;
27+
}
28+
}

src/Serializer/MaxDepthHandler.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace SumoCoders\FrameworkCoreBundle\Serializer;
4+
5+
use Doctrine\ORM\Mapping\Id;
6+
7+
class MaxDepthHandler
8+
{
9+
public function __invoke($innerObject, $outerObject, string $attributeName, string $format = null, array $context = [])
10+
{
11+
return $this->getId($innerObject);
12+
}
13+
14+
private function getId(object $object): ?string
15+
{
16+
$reflectionClass = new \ReflectionClass($entity);
17+
$properties = $reflectionClass->getProperties();
18+
19+
foreach ($properties as $property) {
20+
if ($property->getAttributes(Id::class)) {
21+
$property->setAccessible(true);
22+
return (string) $property->getValue($entity);
23+
}
24+
}
25+
26+
return null;
27+
}
28+
}

0 commit comments

Comments
 (0)