protected function saveManyToMany(array $relationship, $alias, Collection $collection, EntityMetadata $childMetadata, $ourValue, $ourField, $theirField)
 {
     if (!empty($this->relationshipCascade[$alias])) {
         /** @var RepositoryInterface $childRepo */
         $childRepo = $this->relationshipCascade[$alias];
         // save all entities currently in the collection
         foreach ($collection->getAddedEntities() as $child) {
             $childRepo->save($child);
         }
     }
     // We will be doing operations on an intermediary join table. As Reposition works with EntityMetadata, we
     // need to create the metadata for the intermediary
     $intermediaryMetadata = $this->metadataProvider->getEntityMetadataForIntermediary($relationship[EntityMetadata::METADATA_RELATIONSHIP_JOIN_TABLE]);
     // generate the relationship metadata used on this collection
     $intermediaryRelationship = [EntityMetadata::METADATA_RELATIONSHIP_TYPE => EntityMetadata::RELATIONSHIP_TYPE_MANY_TO_ONE];
     $manyToManyRelationships = ["ours" => $this->entityMetadata->getCollection() . "_" . $ourField, "theirs" => $childMetadata->getCollection() . "_" . $theirField];
     foreach ($manyToManyRelationships as $relationshipAlias => $intermediaryOurField) {
         $intermediaryRelationship[EntityMetadata::METADATA_RELATIONSHIP_OUR_FIELD] = $intermediaryOurField;
         $intermediaryRelationship[EntityMetadata::METADATA_RELATIONSHIP_ALIAS] = $relationshipAlias;
         $intermediaryMetadata->addRelationshipMetadata($this->entityMetadata->getEntity(), $intermediaryRelationship);
     }
     // process added and removed children
     $added = $collection->getAddedEntities();
     $removed = $collection->getRemovedEntities();
     if (!empty($added)) {
         $insert = $this->queryBuilder->save($intermediaryMetadata, ["saveType" => "insert"]);
         // create an array of values to use, for each entity we're adding
         foreach ($added as $child) {
             // we have to use the actual field names here as we're saving an array, rather than a class instance
             $entityArray = [$manyToManyRelationships["ours"] => $ourValue, $manyToManyRelationships["theirs"] => $childMetadata->getEntityValue($child, $theirField)];
             $insert->entity($entityArray);
         }
         $this->doQuery($insert, ["output" => "raw"]);
     }
     if (!empty($removed)) {
         $delete = $this->queryBuilder->delete($intermediaryMetadata);
         // delete rows where the parent value is X and the child value is in the list
         $filters = ["ours" => $ourValue, "theirs" => $this->condition("in", $removed)];
         $this->createWhereFromFilters($delete, $filters);
         $this->doQuery($delete, ["output" => "raw"]);
     }
 }
Example #2
0
 public function testDeduping()
 {
     // test adding then removing
     $collection = new Collection();
     $collection->setChangeTracking();
     $collection->add($this->entity1);
     $collection->add($this->entity2);
     $collection->remove($this->entity1);
     $added = $collection->getAddedEntities();
     $this->assertCount(1, $added, "Check the added entity array only has one entry");
     $this->assertCount(0, $collection->getRemovedEntities(), "Check the removed entity array has no entries");
     $this->assertSame($this->entity2, array_pop($added));
     // test removing then adding
     $collection = new Collection();
     $collection->add($this->entity1);
     $collection->add($this->entity2);
     $collection->setChangeTracking();
     $collection->remove($this->entity1);
     $collection->remove($this->entity2);
     $collection->add($this->entity2);
     $collection->add($this->entity3);
     $added = $collection->getAddedEntities();
     $removed = $collection->getRemovedEntities();
     $this->assertCount(1, $added, "Check the added entity array only has one entry");
     $this->assertCount(1, $removed, "Check the removed entity array has no entries");
     $this->assertSame($this->entity3, array_pop($added));
     $this->assertSame($this->entity1, array_pop($removed));
 }