Files
awo-hamburg-intranet/mysyde/common/classes/GenericCRUDObjectStorageUnitOfWork.php

238 lines
8.3 KiB
PHP
Raw Normal View History

2026-02-17 14:56:23 +01:00
<?php
namespace DynCom\mysyde\common\classes;
use DynCom\mysyde\common\interfaces\CRUDObjectStorage;
use DynCom\mysyde\common\interfaces\Entity;
use DynCom\mysyde\common\interfaces\Observer;
use DynCom\mysyde\common\interfaces\UnitOfWorkInterface;
/**
* Created by PhpStorm.
* User: Bauer
* Date: 08.07.2015
* Time: 13:59
*/
class GenericCRUDObjectStorageUnitOfWork implements UnitOfWorkInterface,Observer
{
const ENTITY_STATE_NEW = 'ENTITY_STATE_NEW';
const ENTITY_STATE_CLEAN = 'ENTITY_STATE_CLEAN';
const ENTITY_STATE_DIRTY = 'ENTITY_STATE_DIRTY';
const ENTITY_STATE_REMOVED = 'ENTITY_STATE_REMOVED';
const EVENT_SUBSTR_MODEL_CHANGED = '.changed';
protected $storage;
protected $newEntities;
protected $cleanEntities;
protected $cleanEntitiesInit;
protected $dirtyEntities;
protected $removedEntities;
/**
* GenericCRUDObjectStorageUnitOfWork constructor.
* @param CRUDObjectStorage $storage
*/
public function __construct(CRUDObjectStorage $storage) {
$this->storage = $storage;
}
/**
* @param $eventName
* @param $data
*/
public function notify($eventName, $data) {
$className = get_class($data);
if(!$className || !($data instanceof Entity)) return;
$id = $data->getID();
$this->checkEventForChangedClean($eventName,$className,$id);
}
/**
* @param $eventName
* @param $className
* @param $id
*/
protected function checkEventForChangedClean($eventName, $className, $id) {
if(array_key_exists($className,$this->cleanEntities) && array_key_exists($id,$this->cleanEntities[$className]) && false !== stripos($eventName,self::EVENT_SUBSTR_MODEL_CHANGED)) {
if(isset($this->cleanEntities[$className][$id])) {
$entity = $this->cleanEntities[$className][$id];
$this->dirtyEntities[$className][$id] = $entity;
unset($this->cleanEntities[$className][$id]);
}
}
}
/**
* @param Entity $entity
*/
public function registerNew(Entity $entity) {
$className = get_class($entity);
$id = $entity->getID();
if((int)$id > 0) {
throw new \BadMethodCallException(
"Entity must not have an ID > 0 to be registered as new."
);
}
$objHash = spl_object_hash($entity);
$this->newEntities[$className][$objHash] = &$entity;
}
/**
* @param Entity $entity
*/
public function registerClean(Entity $entity) {
$className = get_class($entity);
$id = $entity->getID();
if(!(int)$id > 0) {
throw new \BadMethodCallException(
"Entity needs a not-null id to be registered as clean."
);
}
if(
(array_key_exists($className,$this->dirtyEntities) && array_key_exists($id,$this->dirtyEntities[$className]))
|| (array_key_exists($className,$this->removedEntities) && array_key_exists($id,$this->removedEntities[$className]))) {
throw new \BadMethodCallException(
"Entity must not already be registered as dirty or removed to be registered as Clean"
);
}
$this->cleanEntitiesInit[$className][$id] = clone $entity;
$this->cleanEntities[$className][$id] = &$entity;
}
/**
* @param Entity $entity
*/
public function registerDirty(Entity $entity) {
$className = get_class($entity);
$id = $entity->getID();
if(!(int)$id > 0) {
throw new \BadMethodCallException(
"Entity needs a not-null id to be registered as dirty."
);
}
unset($this->cleanEntities[$className][$id],$this->removedEntities[$className][$id]);
$this->dirtyEntities[$className][$id] = &$entity;
}
/**
* @param Entity $entity
*/
public function registerRemoved(Entity $entity) {
$className = get_class($entity);
$id = $entity->getID();
if(!(int)$id > 0) {
throw new \BadMethodCallException(
"Entity needs a not-null id to be registered as removed."
);
}
unset($this->cleanEntities[$className][$id],$this->dirtyEntities[$className][$id]);
$this->removedEntities[$className][$id] = &$entity;
}
/**
* @param Entity $entity
* @param $state
*/
public function registerEntity(Entity $entity, $state) {
switch($state) {
case self::ENTITY_STATE_NEW:
$this->registerNew($entity);
return;
case self::ENTITY_STATE_CLEAN:
$this->registerClean($entity);
return;
case self::ENTITY_STATE_DIRTY:
$this->registerDirty($entity);
return;
case self::ENTITY_STATE_REMOVED:
$this->registerRemoved($entity);
return;
default: break;
}
throw new \InvalidArgumentException(
"State must be one of ENTITY_STATE_NEW, ENTITY_STATE_CLEAN, ENTITY_STATE_DIRTY, ENTITY_STATE_REMOVED."
);
}
/**
* @param Entity $entity
*/
public function unregisterEntity(Entity $entity) {
$className = get_class($entity);
$id = $entity->getID();
$objHash = spl_object_hash($entity);
unset(
$this->newEntities[$className][$objHash],
$this->cleanEntities[$className][$id],
$this->dirtyEntities[$className][$id],
$this->removedEntities[$className][$id]
);
}
public function rollback() {
//Look for entities in dirty / removed that had initially
//been registered as clean and then moved to dirty / removed through changes.
//Reset such entities to their initial state cloned on registration
foreach($this->dirtyEntities as $className => &$entityArr) {
foreach($entityArr as $id => $obj) {
if(array_key_exists($id,$this->cleanEntitiesInit[$className])) {
$oldState = $this->cleanEntitiesInit[$className][$id];
//Initially stored by reference,
//So this resets the referenced entity to init state
//And then deletes the reference in the array
$obj = $entityArr[$id];
$obj = $oldState;
unset($entityArr[$id]);
$this->cleanEntities[$className][$id] = $obj;
}
}
}
unset($entityArr);
foreach($this->removedEntities as $className => &$entityArr2) {
foreach($entityArr2 as $id => $obj) {
if(array_key_exists($id,$this->cleanEntitiesInit[$className])) {
$oldState = $this->cleanEntitiesInit[$className][$id];
//Initially stored by reference,
//So this resets the referenced entity to init state
//And then deletes the reference in the array
$obj = $entityArr2[$id];
$obj = $oldState;
unset($entityArr2[$id]);
$this->cleanEntities[$className][$id] = $obj;
}
}
}
unset($entityArr2);
}
public function clear() {
$this->newEntities = [];
$this->cleanEntitiesInit = [];
$this->cleanEntities = [];
$this->dirtyEntities = [];
$this->removedEntities = [];
}
public function commit() {
foreach($this->newEntities as $className => $objArr) {
foreach($objArr as $entity) {
$this->storage->create($entity);
}
}
foreach($this->dirtyEntities as $className => $objArr) {
foreach($objArr as $id => $entity) {
$this->storage->update($entity);
}
}
foreach($this->removedEntities as $className => $objArr) {
foreach($objArr as $id => $entity) {
$this->storage->delete($entity);
}
}
}
}