init
This commit is contained in:
238
mysyde/common/classes/GenericCRUDObjectStorageUnitOfWork.php
Normal file
238
mysyde/common/classes/GenericCRUDObjectStorageUnitOfWork.php
Normal file
@@ -0,0 +1,238 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user