Es gibt Anwendungsfälle, bei denen jede Änderung an einem oder mehrerer Models festgehalten bzw. archiviert werden sollte.

Dies ist mittels des Doctrine Behaviors “Versionable” relativ einfach und vor allem transparent umzusetzen (Doctrine Behaviors).

Mein Versuch war es, dies in TYPO3 Flow einzubauen. Jedoch scheiterte mein Versuch da ich kein umfassendes Doctrine Wissen hatte um dies einzubauen.

Nun möchte ich hier einen Alternativen Weg vorstellen, welcher sich einem Symfony2 Bundle von SimpleThings bedient (GitHub: simplethings/entityaudit).

Um dieses SymfonyBundle in TYPO3 Flow lauffähig und schön zu integrieren, werden wir im folgenden eine Bridge zwischen Flow und dem Symfony Bundle erstellen.

SimpleThings EntityAudit installieren

Die Installation des SimpleThings/EntityAudit Bundles in unserem Flow Framework gestaltet sich dank Composer als relativ einfach.
Wir führen den Composer Befehl einfach im Root Verzeichnis der TYPO3 Flow Anwendung aus:

composer require "simplethings/entity-audit-bundle"

Hiermit wird das Symfony Bundle im Packages/Library Verzeichnis abgelegt.

Um dieses Bundle von Flows Object Management auszuschließen, fügenden wir folgende Einstellung in unserer Settings.yaml hinzu:

TYPO3:
  Flow:
    object:
      excludeClasses:
        'simplethings.entityauditbundle': ['SimpleThings\\EntityAudit\\.*']

Flow AOP Bridge

Als nächstes bedienen wir uns dem mächtigen AOP Features von TYPO3 Flow um unser Symfony Bundle zu integrieren.
Dazu legen wir einen neuen AOP Aspect in unserem Package an:

buildEventManager())")
     * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint
     * @return \Doctrine\Common\EventManager
     */
    public function registerSimpleThingsAuditManager(\TYPO3\Flow\Aop\JoinPointInterface $joinPoint) {
        $emInstance = $joinPoint->getAdviceChain()->proceed($joinPoint);

        // Hier festlegen, welche Entities versioniert werden sollen
        $auditEntitiesArray = array('Vendor\Package\Domain\Model\MyEntity');

        $entityAuditConf = new \SimpleThings\EntityAudit\AuditConfiguration();
        $entityAuditConf->setAuditedEntityClasses($auditEntitiesArray);

        $entityAuditManagerInstance = new \SimpleThings\EntityAudit\AuditManager($entityAuditConf);
        $entityAuuditManagerInstance->registerEvents($emInstance);
        
        return $emInstance;
    }
}
?>

Als nächstes führen wir ein

# Database aktualisieren (Audit Tables erstellen)
./flow doctrine:update

auf der Shell aus und prüfen anschließend unsere Datenbank Tabellen. Wenn alles funktioniert hat, sollte es nun passend zu unserer MyEntity Tabelle eine weitere MyEntity_audit Tabelle sowie eine revision Tabelle geben.

Nun solltet ihr testen, ob bei einer Änderung von MyEntity auch gleichzeitig eine entsprechende Revision und ein Eintrag in der MyEntity_audit Tabelle angelegt wird.

Flow Annotation “Versionable”

Natürlich ist es unschön, die zu versionierenden Models innerhalb des Aspects im Array hardcoded einzutragen. Eine andere Möglichkeit könnte hier die Settings.yaml sein, in welcher die zu versionierenden Models eingetragen werden können.
Am saubersten halte ich jedoch die Möglichkeit, hierfür eine eigene TYPO3 Flow Annotation zu erstellen.

Hierzu legen wir eine neue Klasse mit dem Namen “AuditEntity” an und befüllen Sie mit dem Code für eine Annotation
Beispielnamespace: Vendor\Package\Audit\Annotations\AuditEntity

/**
 * @Annotation
 * @Target("CLASS")
 */
final class AuditEntity {
/** Nothing here, it's only a Marker Class */
}

Nun lassen sich innerhalb EntityAuditRegisterAspect mittels des TYPO3 Flow Reflection Services alle Models ermitteln, welche die neue Annotation tragen:

/**
 * @var \TYPO3\Flow\Reflection\ReflectionService
 * @Flow\Inject
 */
protected $reflectionService;

$annotatedModels = $this->reflectionService->getClassNamesByAnnotation('Vendor\Package\Audit\Annotations\AuditEntity');

Um sich die versionierten Models später nochmal auslesen lassen zu können, bringt das SimpleThings EntityAudit Bundle einen AuditReader mit GitHub: SimpleThings/EntityAudit AuditReader. Diesen können wir ebenfalls in unserem TYPO3 Flow Package verwenden.