/** * Kompiliert den Synchronizer und initialisiert * * wenn angegeben $add angegben wird, wird diese Closure mit $entity (der Parameter der init() Funktion) und $otherEntity aufgerufen * bei $add ist $otherEntity ein Entity aus der $toCollection welches nicht in der $fromColleciton ist * bei $remove ist $otherEntity ein Entity aus der $fromCollection welches nicht in der $toCollection ist * als dritter parameter wird das $repository des Entities in der Collection übergeben (also nicht das von $entity) * * die Standard-Adder sind nur für den Fall, dass diese Klasse auch die owning Side ist * sie rufen also $entity->addXXX($toEntity) auf * bzw * $entity->removeXXX($fromEntity) * * @param Closure $adder function ($entity, $toEntity, $collectionRepository) persist nicht vergesen! * @param Closure $remover function ($entity, $fromEntity, $collectionRepository) */ public function init(Entity $entity, Closure $adder = NULL, Closure $remover = NULL) { parent::init($entity); list($add, $remove) = $this->getRelationInterface(); if (!$adder) { $adder = function ($entity, $toEntity, $repository) use($add) { $repository->persist($toEntity); $entity->{$add}($toEntity); }; } if (!$remover) { $remover = function ($entity, $fromEntity, $repository) use($remove) { $repository->persist($fromEntity); $entity->{$remove}($fromEntity); }; } $repository = $this->collectionRepository; // insert: in $toCollection gibt es ein $toEntity, welches noch nicht in $fromCollection war $this->innerSynchronizer->onInsert(function ($toEntity) use($repository, $entity, $adder) { $adder($entity, $toEntity, $repository); }); // update bzw merge: das $toEntity war bereits in der $fromCollection und ist in der $toCollection $this->innerSynchronizer->onUpdate(function ($toEntity) use($repository, $entity, $adder) { $adder($entity, $toEntity, $repository, $isUpdate = TRUE); }); // delete: das $fromEntity war vorher in der $fromCollection und ist nicht mehr in der $toCollection $this->innerSynchronizer->onDelete(function (Entity $fromEntity) use($entity, $remover, $repository) { $remover($entity, $fromEntity, $repository); // wenn $fromEntity 0 verknüpfungen hat, könnte man es hier auch löschen, dies macht aber das relationinterface }); return $this; }
/** * Initialisiert die Defaults für alle on* Methoden für das Entity mit der Collection * * ein CollectionSynchronizer kann mehrere Collections eines Types von mehreren Entities synchronisieren wenn jeweils init() für das aktuelle Entity aufgerufen wird * * new Synchronizer(); * foreach ($articles as $article) { * $synchronizer->init($article); * * $synchronizer->process($article->getTags(), $formData[$article->getId()]); * } */ public function init(Entity $entity) { parent::init($entity); $hydrator = $this->hydrator; $factory = $this->factory; $repository = $hydrator->getRepository(); $identifier = $factory->getEntityMeta()->getIdentifier(); $skipFields = array(); if ($identifier->isAutogeneratedValue()) { $skipFields[$identifier->getName()] = TRUE; } list($add, $remove) = $this->getRelationInterface(); // hydrate $this->onHydrate(function ($toObject) use($hydrator) { return $hydrator->getEntity((array) $toObject); // convention: $field=>value für alle unique constraint-felder }); // hash $this->onHash(function (Entity $entity) { return $entity->getIdentifier(); }); // insert $this->onInsert(function ($toObject) use($factory, $repository, $entity, $add, $skipFields) { $factory->reset(); foreach ($toObject as $field => $value) { if (!array_key_exists($field, $skipFields)) { $factory->set($field, $value); } } $collectionEntity = $factory->getEntity(); $entity->{$add}($collectionEntity); $repository->persist($collectionEntity); }); // update (merge) $this->onUpdate(function (Entity $collectionEntity, $toObject) use($repository, $entity, $add, $skipFields) { foreach ($toObject as $field => $value) { if (!array_key_exists($field, $skipFields)) { $collectionEntity->callSetter($field, $value); } } $entity->{$add}($collectionEntity); $repository->persist($collectionEntity); }); // delete $this->onDelete(function (Entity $collectionEntity) use($entity, $remove) { $entity->{$remove}($collectionEntity); // wenn tag 0 verknüpfungen hat, könnte man es hier auch löschen }); return $this; }