DamienHarper/auditor-bundle

Softdeleteable Entities not Logging Deletion

ixalsera opened this issue ยท 5 comments

Q A
auditor-bundle version 5.0.3
PHP version 7.4.32
Database MySQL

Summary

Almost exactly the same issue as #122, entities tagged as soft-deletable do not seem to fire an audit event. Regular deletions are logged, updates and insertions are also logged. The deletedAt column is updated with the time when a soft-delete happens. Using v1.7.0 of StofDoctrineExtensionsBundle

Current behavior

When removing an entity annotated with @Gedmo\SoftDeletable (also tried with YAML mapping previously and did not work) with $entitymanager->remove($entity);, the entity is soft deleted as expected but no audit log entry appears for the deletion.

How to reproduce

  1. Annotate an entity with @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false)
  2. Create an instance of the entity and persist it
  3. Delete the persisted entity using the entity manager

Expected behavior

Entity should be soft deleted, an update audit entry showing the setting of deletedAt field should be generated.

I managed somehow to fix it by overwriting the DoctrineSubscriber priority like this (in my app ./config/services.yaml file):

DH\Auditor\Provider\Doctrine\Auditing\Transaction\TransactionManager:
    arguments: ['@DH\Auditor\Provider\Doctrine\DoctrineProvider']

DH\Auditor\Provider\Doctrine\Auditing\Event\DoctrineSubscriber:
    arguments: ['@DH\Auditor\Provider\Doctrine\Auditing\Transaction\TransactionManager']
    tags:
        - { name: doctrine.event_subscriber, priority: 1000 }

This results in having on the audit table a remove entry with the soft deleted object, it's a working solution for me. The perfect solution will be actually to have an update entry with the old and new values for the deletedAt property, but I couldn't manage to have this, if you have more success, please post the solution.

The same bug here. v. 5.0.0

    class: DH\Auditor\Provider\Doctrine\Persistence\Event\CreateSchemaListener
    arguments: ['@DH\Auditor\Provider\Doctrine\DoctrineProvider']
    tags:
      - { name: doctrine.event_subscriber, priority: 1000000 }

  DH\Auditor\Provider\Doctrine\Persistence\Event\TableSchemaSubscriber:
    class: DH\Auditor\Provider\Doctrine\Persistence\Event\TableSchemaSubscriber
    arguments: ['@DH\Auditor\Provider\Doctrine\DoctrineProvider']
    tags:
      - { name: doctrine.event_subscriber, priority: 1000000 }

I had to overwrite the priority of the services above to have some sort of working solution.
Still have some inconsistencies, though. It always logs the deletion of the entity, but sometimes it logs the update to the deletedAt column too.

using version 5.2 of the auditor bundle
"damienharper/auditor-bundle": "^5.2"
with gedmo doctrine extensions 3
"gedmo/doctrine-extensions": "^3.0",

Hi,
we are also suffering from this issue with the versions

  • PHP: 8.2
  • Symfony 5.4
  • damienharper/auditor-bundle: 5.2.5
  • gedmo/doctrine-extensions: 3.15.0

I investigated this issue based on the comments here and found a bit of hacky but less disrupting way around this issue without duplicate or inconsistent audit logs by implementing a preFlush event listener which could be helpful for others as well as long as this issue persists.

<?php

namespace App\EventListener;

use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Event\PreFlushEventArgs;
use Doctrine\ORM\Events;
use Gedmo\SoftDeleteable\SoftDeleteableListener;

#[AsDoctrineListener(event: Events::preFlush)]
class PreFlushListener
{
    /**
     * Hacky way to swap the priority of the {@see SoftDeleteableListener} to be applied after the {@see DoctrineSubscriber}.
     * @param PreFlushEventArgs $eventArgs
     * @return void
     */
    public function preFlush(PreFlushEventArgs $eventArgs): void
    {
        $eventManager = $eventArgs->getObjectManager()->getEventManager();
        $eventListeners = $eventManager->getListeners(Events::onFlush);
        foreach ($eventListeners as $eventListener) {
            if ($eventListener instanceof SoftDeleteableListener) {
                $softDeleteableListener = $eventListener;
                $eventManager->removeEventListener(Events::onFlush, $softDeleteableListener);
                break;
            }
        }
        if (isset($softDeleteableListener)) {
            $eventManager->addEventListener(Events::onFlush, $softDeleteableListener);
        }
    }
}

Notes: I have notes in one of my subscribers while listening to LifeCycle events.
/**
* You need to listen to preRemove if you use soft delete
* from Doctrine extensions, because it prevents postRemove
* from being called.
*/