Skip to content

Commit

Permalink
Better JSON support (#225)
Browse files Browse the repository at this point in the history
* Tweak `phpdoc_to_comment` rule (PHP-CS-Fixer )

* auditor now keeps track of changes inside json data (addition/removal/update of fields)
  • Loading branch information
DamienHarper authored Oct 24, 2024
1 parent e6909e5 commit 4452695
Show file tree
Hide file tree
Showing 6 changed files with 367 additions and 23 deletions.
3 changes: 3 additions & 0 deletions .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
'phpdoc_to_param_type' => true,
'phpdoc_to_property_type' => true,
'phpdoc_to_return_type' => true,
'phpdoc_to_comment' => [
'ignored_tags' => ['todo', 'var']
],
'regular_callable_call' => true,
'simplified_if_return' => true,
'get_class_to_class_keyword' => true,
Expand Down
101 changes: 96 additions & 5 deletions src/Provider/Doctrine/Auditing/Transaction/AuditTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,36 @@ private function value(EntityManagerInterface $entityManager, Type $type, mixed
}

/**
* Computes a usable diff.
* Computes a usable diff formatted as follow:
* [
* // field1 value has changed
* 'field1' => [
* 'old' => $oldValue, // value before change
* 'new' => $newValue // value after change
* ],
* // field2 value has been added
* 'field2' => [
* 'new' => $newValue
* ],
* ...
* // jsonField1 has changed
* 'jsonField1' => [
* // field1 value has changed
* 'field1' => [
* 'old' => $oldValue,
* 'new' => $newValue
* ],
* // field2 value has been added
* 'field2' => [
* 'new' => $newValue
* ],
* // field3 value has been removed
* 'field3' => [
* 'old' => $oldValue
* ],
* ...
* ],
* ]
*
* @throws MappingException
* @throws Exception
Expand All @@ -152,6 +181,7 @@ private function diff(EntityManagerInterface $entityManager, object $entity, arr
continue;
}

$type = null;
if (
!isset($meta->embeddedClasses[$fieldName])
&& $meta->hasField($fieldName)
Expand All @@ -172,10 +202,20 @@ private function diff(EntityManagerInterface $entityManager, object $entity, arr
}

if ($o !== $n) {
$diff[$fieldName] = [
'new' => $n,
'old' => $o,
];
if (isset($type) && Type::getType(Types::JSON) === $type) {
/**
* @var ?array $o
* @var ?array $n
*/
$diff[$fieldName] = $this->deepDiff($o, $n);
} else {
if (null !== $o) {
$diff[$fieldName]['old'] = $o;
}
if (null !== $n) {
$diff[$fieldName]['new'] = $n;
}
}
}
}

Expand Down Expand Up @@ -257,4 +297,55 @@ private function blame(): array
'username' => $username,
];
}

private function deepDiff(?array $old, ?array $new): array
{
$diff = [];

// Check for differences in $old
if (null !== $old && null !== $new) {
foreach ($old as $key => $value) {
if (!\array_key_exists($key, $new)) {
// $key does not exist in $new, it's been removed
$diff[$key] = \is_array($value) ? $this->formatArray($value, 'old') : ['old' => $value];
} elseif (\is_array($value) && \is_array($new[$key])) {
// both values are arrays, compare them recursively
$recursiveDiff = $this->deepDiff($value, $new[$key]);
if ([] !== $recursiveDiff) {
$diff[$key] = $recursiveDiff;
}
} elseif ($new[$key] !== $value) {
// values are different
$diff[$key] = ['old' => $value, 'new' => $new[$key]];
}
}
}

// Check for new elements in $new
if (null !== $new) {
foreach ($new as $key => $value) {
if (!\array_key_exists($key, $old ?? [])) {
// $key does not exist in $old, it's been added
$diff[$key] = \is_array($value) ? $this->formatArray($value, 'new') : ['new' => $value];
}
}
}

return $diff;
}

private function formatArray(array $array, string $prefix): array
{
$result = [];

foreach ($array as $key => $value) {
if (\is_array($value)) {
$result[$key] = $this->formatArray($value, $prefix);
} else {
$result[$key][$prefix] = $value;
}
}

return $result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace DH\Auditor\Tests\Provider\Doctrine;
namespace DH\Auditor\Tests\Provider\Doctrine\Auditing;

use DH\Auditor\Provider\Doctrine\DoctrineProvider;
use DH\Auditor\Provider\Doctrine\Service\AuditingService;
Expand Down Expand Up @@ -111,19 +111,11 @@ private function createAndInitDoctrineProvider(): void
$this->provider = new DoctrineProvider($this->createProviderConfiguration());

$entityManager = $this->createEntityManager([
__DIR__.'/../../../src/Provider/Doctrine/Auditing/Annotation',
__DIR__.'/Fixtures/Entity/Inheritance',
__DIR__.'/../../../../src/Provider/Doctrine/Auditing/Annotation',
__DIR__.'/../Fixtures/Entity/Inheritance',
]);
$this->provider->registerStorageService(new StorageService('default', $entityManager));
$this->provider->registerAuditingService(new AuditingService('default', $entityManager));
// $this->provider->registerEntityManager(
// $this->createEntityManager([
// __DIR__.'/../../../src/Provider/Doctrine/Auditing/Annotation',
// __DIR__.'/Fixtures/Entity/Inheritance',
// ]),
// DoctrineProvider::BOTH,
// 'default'
// );

$auditor->registerProvider($this->provider);
}
Expand Down
Loading

0 comments on commit 4452695

Please sign in to comment.