From 65691a8d9a4db5dd37301d04932286d8b2a1d55d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20R=C3=BCfenacht?= Date: Tue, 17 Oct 2023 16:27:30 +0200 Subject: [PATCH] fix: use onFlush instead since Doctrine changed functionality --- README.md | 193 ++++++++++++++++++ readme.md | 71 ------- src/Entity/AuditManyToOneTriggerInterface.php | 7 +- src/Entity/AuditTriggerTrait.php | 2 +- .../AuditTriggerSubscriber.php | 48 +++-- tests/App/Entity/Contact.php | 4 +- tests/ControllerTest.php | 2 +- 7 files changed, 230 insertions(+), 97 deletions(-) create mode 100644 README.md delete mode 100644 readme.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..283e0b5 --- /dev/null +++ b/README.md @@ -0,0 +1,193 @@ +# CrudHistoryBundle + +## Basic Usage + +### config/routes.yaml +```yaml +whatwedo_crud_history_bundle: + resource: "@whatwedoCrudHistoryBundle/Resources/config/routing.yml" + prefix: / + +``` + +### src/Definition/History/PersonHistoryDefinition.php + +```php +company = $company; + } + + // ... + + public function triggerManyToOne(): array + { + $this->getCompany()->triggerAudit(); + + return [$this->getCompany()]; + } +} +``` + +The `triggerManyToOne` should return all entities where the audit has been triggered (`triggerAudit`). This array can contain `null` values. +This allows you to call getters inside this array and save you some space for null checks. + +### src/Entity/Company.php +```php +namespace whatwedo\CrudHistoryBundle\Tests\App\Entity; + +use App\Repository\CompanyRepository; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; +use Doctrine\ORM\Mapping as ORM; +use whatwedo\CrudHistoryBundle\Entity\AuditTriggerInterface; +use whatwedo\CrudHistoryBundle\Entity\AuditTriggerTrait; + +#[ORM\Entity(repositoryClass: CompanyRepository::class)] +class Company implements AuditTriggerInterface +{ + use AuditTriggerTrait; + + #[ORM\OneToMany(targetEntity: 'Contact', mappedBy: 'company')] + private Collection $contacts; + + public function __construct() + { + $this->contacts = new ArrayCollection(); + } + + // ... +} +``` + +### src/Definition/CompanyDefinition.php +```php +namespace whatwedo\CrudHistoryBundle\Tests\App\Definition; + +use araise\CrudBundle\Definition\AbstractDefinition; +use whatwedo\CrudHistoryBundle\Definition\HasHistoryDefinition; +use whatwedo\CrudHistoryBundle\Tests\App\Definition\History\CompanyHistoryDefinition; +use whatwedo\CrudHistoryBundle\Tests\App\Entity\Company; + +class CompanyDefinition extends AbstractDefinition implements HasHistoryDefinition +{ + public static function getEntity(): string + { + return Company::class; + } + + public static function getCapabilities(): array + { + return array_merge( + [HistoryPage::HISTORY], + parent::getCapabilities() + ); + } + + public function getHistoryDefinition(): string + { + return CompanyHistoryDefinition::class; + } +} +``` + +### App/Definition/History/CompanyHistoryDefinition.php +```php +namespace whatwedo\CrudHistoryBundle\Tests\App\Definition\History; + +use whatwedo\CrudHistoryBundle\Definition\HistoryAssociatedClass; +use whatwedo\CrudHistoryBundle\Definition\HistoryDefinitionInterface; +use whatwedo\CrudHistoryBundle\Tests\App\Entity\Company; +use whatwedo\CrudHistoryBundle\Tests\App\Entity\Contact; + +class CompanyHistoryDefinition implements HistoryDefinitionInterface +{ + public function getMainClass(): string + { + return Company::class; + } + + /** + * @return HistoryAssociatedClass[] + */ + public function getAssociatedClasses(): array + { + return [ + new HistoryAssociatedClass(Contact::class, []), + ]; + } + + public function getChildDefinitions(): array + { + return []; + } +} +``` \ No newline at end of file diff --git a/readme.md b/readme.md deleted file mode 100644 index 381dcd5..0000000 --- a/readme.md +++ /dev/null @@ -1,71 +0,0 @@ -## Basic Usage - -config/routes.yaml -```yaml -whatwedo_crud_history_bundle: - resource: "@whatwedoCrudHistoryBundle/Resources/config/routing.yml" - prefix: / - -``` - -src/Definition/History/PersonHistoryDefinition.php - -```php -auditTrigger; } diff --git a/src/EventSubscriber/AuditTriggerSubscriber.php b/src/EventSubscriber/AuditTriggerSubscriber.php index 83772ec..b9016f7 100644 --- a/src/EventSubscriber/AuditTriggerSubscriber.php +++ b/src/EventSubscriber/AuditTriggerSubscriber.php @@ -31,45 +31,49 @@ use Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface; use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Event\LifecycleEventArgs; +use Doctrine\ORM\Event\OnFlushEventArgs; use Doctrine\ORM\Events; use whatwedo\CrudHistoryBundle\Entity\AuditManyToOneTriggerInterface; final class AuditTriggerSubscriber implements EventSubscriberInterface { - public function __construct( - protected EntityManagerInterface $entityManager - ) { - } - public function getSubscribedEvents(): array { return [ - Events::prePersist, - Events::preUpdate, - Events::postFlush, + Events::onFlush, ]; } - public function preUpdate($entity): void + public function onFlush(OnFlushEventArgs $args): void { - $this->triggerManyToOneAssciations($entity); - } + $entityManager = $args->getObjectManager(); + $unitOfWork = $entityManager->getUnitOfWork(); - public function prePersist($entity): void - { - $this->triggerManyToOneAssciations($entity); - } + $updatedEntities = $unitOfWork->getScheduledEntityUpdates(); + $insertedEntities = $unitOfWork->getScheduledEntityInsertions(); - public function postFlush($entity): void - { - return; + if (count($updatedEntities) > 0 || count($insertedEntities) > 0) { + $this->handleEntities($insertedEntities, $entityManager); + $this->handleEntities($updatedEntities, $entityManager); + } } - private function triggerManyToOneAssciations(LifecycleEventArgs $eventArgs): void + /** + * @param object[] $entities + */ + private function handleEntities(array $entities, EntityManagerInterface $entityManager): void { - if ($eventArgs->getEntity() instanceof AuditManyToOneTriggerInterface) { - $eventArgs->getEntity()->triggerManyToOne(); + foreach ($entities as $entity) { + if ($entity instanceof AuditManyToOneTriggerInterface) { + $touchedEntities = $entity->triggerManyToOne(); + + foreach ($touchedEntities as $touchedEntity) { + if ($touchedEntity === null) { + continue; + } + $entityManager->getUnitOfWork()->recomputeSingleEntityChangeSet($entityManager->getClassMetadata(get_class($touchedEntity)), $touchedEntity); + } + } } } } diff --git a/tests/App/Entity/Contact.php b/tests/App/Entity/Contact.php index 03a0d87..59ed09c 100644 --- a/tests/App/Entity/Contact.php +++ b/tests/App/Entity/Contact.php @@ -65,9 +65,11 @@ public function setCompany(Company $company): void $this->company = $company; } - public function triggerManyToOne() + public function triggerManyToOne(): array { $this->getCompany()->triggerAudit(); + + return [$this->getCompany()]; } public function __toString(): string diff --git a/tests/ControllerTest.php b/tests/ControllerTest.php index 1bed122..1fe9b64 100644 --- a/tests/ControllerTest.php +++ b/tests/ControllerTest.php @@ -29,7 +29,7 @@ public function testGetHistory(): void ]); $crawler = $client->request('GET', $url); - $this->assertResponseIsSuccessful(); + self::assertResponseIsSuccessful(); $this->assertnotSame('', $crawler->html()); }