Skip to content

Commit 6b0811f

Browse files
committed
feat: cleanup all relations for empty array
1 parent 21066d4 commit 6b0811f

File tree

2 files changed

+87
-35
lines changed

2 files changed

+87
-35
lines changed

src/DataAbstractionLayer/WriteCommandExtractorDecorator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ private function registerRelations(array $rawData, WriteParameterBag $parameters
267267

268268
$fieldData = $rawData[$field->getPropertyName()] ?? null;
269269

270-
if (!is_array($fieldData) || empty($fieldData)) {
270+
if (!is_array($fieldData)) {
271271
continue;
272272
}
273273

@@ -277,7 +277,7 @@ private function registerRelations(array $rawData, WriteParameterBag $parameters
277277

278278
/**
279279
* @param non-empty-array<non-empty-string, non-empty-string> $parentPrimaryKey
280-
* @param non-empty-array<mixed, mixed> $fieldData
280+
* @param array<mixed, mixed> $fieldData
281281
*/
282282
private function registerRelationsForField(
283283
ManyToManyAssociationField|OneToManyAssociationField $field,

tests/Functional/DataAbstractionLayer/EntityWriteSubscriberTest.php

Lines changed: 85 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Swh\SmartRelationSync\Tests\Functional\DataAbstractionLayer;
66

77
use PHPUnit\Framework\TestCase;
8+
use Shopware\Core\Content\Category\CategoryCollection;
89
use Shopware\Core\Content\Product\ProductCollection;
910
use Shopware\Core\Content\Product\ProductEntity;
1011
use Shopware\Core\Content\Test\Product\ProductBuilder;
@@ -35,33 +36,74 @@ public function testSyncManyToMany(): void
3536
$builder = $this->createProductBuilder()
3637
->category('Test 1');
3738

38-
$this->upsertProductWithRelationCleanup($builder);
39+
$this->upsertProductWithRelationCleanup($builder->build());
3940

4041
$builder = $this->createProductBuilder()
4142
->category('Test 2');
4243

43-
$this->upsertProductWithRelationCleanup($builder);
44+
$this->upsertProductWithRelationCleanup($builder->build());
4445

45-
$criteria = new Criteria([$this->ids->get(self::PRODUCT_NUMBER)]);
46-
$criteria->addAssociation('categories');
47-
48-
$product = $this->searchProductSingle($criteria);
49-
$categories = $product->getCategories();
46+
$categories = $this->loadCategories();
5047
self::assertCount(1, $categories ?? []);
5148
self::assertSame($this->ids->get('Test 2'), $categories?->first()?->getId());
5249
}
5350

51+
public function testSyncManyToManyWithEmptyArray(): void
52+
{
53+
$builder = $this->createProductBuilder()
54+
->category('Test 1');
55+
56+
$this->upsertProductWithRelationCleanup($builder->build());
57+
58+
$payload = $this->createProductBuilder()->build();
59+
$payload['categories'] = [];
60+
61+
$this->upsertProductWithRelationCleanup($payload);
62+
63+
$categories = $this->loadCategories();
64+
self::assertCount(0, $categories ?? []);
65+
}
66+
67+
public function testSyncManyToManyWithoutCleanup(): void
68+
{
69+
$builder = $this->createProductBuilder()
70+
->category('Test 1');
71+
72+
$this->upsertProduct($builder->build());
73+
74+
$builder = $this->createProductBuilder()
75+
->category('Test 2');
76+
77+
$this->upsertProduct($builder->build());
78+
79+
$categories = $this->loadCategories();
80+
self::assertCount(2, $categories ?? []);
81+
}
82+
83+
public function testSyncManyToManyWithoutPayload(): void
84+
{
85+
$builder = $this->createProductBuilder()
86+
->category('Test 1');
87+
88+
$this->upsertProductWithRelationCleanup($builder->build());
89+
90+
$this->upsertProductWithRelationCleanup($this->createProductBuilder()->build());
91+
92+
$categories = $this->loadCategories();
93+
self::assertCount(1, $categories ?? []);
94+
}
95+
5496
public function testSyncOneToMany(): void
5597
{
5698
$productBuilder = $this->createProductBuilder()
5799
->prices('test', 14.28);
58100

59-
$this->upsertProductWithRelationCleanup($productBuilder);
101+
$this->upsertProductWithRelationCleanup($productBuilder->build());
60102

61103
$productBuilder = $this->createProductBuilder()
62104
->prices('test2', 115.0);
63105

64-
$this->upsertProductWithRelationCleanup($productBuilder);
106+
$this->upsertProductWithRelationCleanup($productBuilder->build());
65107

66108
$criteria = new Criteria([$this->ids->get(self::PRODUCT_NUMBER)]);
67109
$criteria->addAssociation('prices');
@@ -72,24 +114,53 @@ public function testSyncOneToMany(): void
72114
self::assertSame($this->ids->get('test2'), $prices?->first()?->getRuleId());
73115
}
74116

117+
protected function loadCategories(): ?CategoryCollection
118+
{
119+
$criteria = new Criteria([$this->ids->get(self::PRODUCT_NUMBER)]);
120+
$criteria->addAssociation('categories');
121+
122+
$product = $this->searchProductSingle($criteria);
123+
return $product->getCategories();
124+
}
125+
75126
private function createProductBuilder(): ProductBuilder
76127
{
77128
return (new ProductBuilder($this->ids, self::PRODUCT_NUMBER))
78129
->name('Test product')
79130
->price(11.5);
80131
}
81132

133+
/**
134+
* @return EntityRepository<ProductCollection>
135+
*/
136+
private function getProductRepository(): EntityRepository
137+
{
138+
/** @var EntityRepository<ProductCollection> $productRepository */
139+
$productRepository = $this->getContainer()->get('product.repository');
140+
assert($productRepository instanceof EntityRepository);
141+
return $productRepository;
142+
}
143+
144+
private function searchProductSingle(Criteria $criteria): ProductEntity
145+
{
146+
$product = $this->getProductRepository()->search($criteria, $this->context)->first();
147+
148+
self::assertInstanceOf(ProductEntity::class, $product);
149+
150+
return $product;
151+
}
152+
82153
/**
83154
* @param array<mixed> $payload
84155
*/
85-
private function executeUpsert(string $entity, array $payload): void
156+
private function upsertProduct(array $payload): void
86157
{
87158
$this->getBrowser()->jsonRequest(
88159
'POST',
89160
'/api/_action/sync',
90161
[
91162
'write-product' => [
92-
'entity' => $entity,
163+
'entity' => 'product',
93164
'action' => 'upsert',
94165
'payload' => [$payload],
95166
],
@@ -102,32 +173,13 @@ private function executeUpsert(string $entity, array $payload): void
102173
}
103174

104175
/**
105-
* @return EntityRepository<ProductCollection>
176+
* @param array<mixed> $payload
106177
*/
107-
private function getProductRepository(): EntityRepository
108-
{
109-
/** @var EntityRepository<ProductCollection> $productRepository */
110-
$productRepository = $this->getContainer()->get('product.repository');
111-
assert($productRepository instanceof EntityRepository);
112-
return $productRepository;
113-
}
114-
115-
private function searchProductSingle(Criteria $criteria): ProductEntity
116-
{
117-
$product = $this->getProductRepository()->search($criteria, $this->context)->first();
118-
119-
self::assertInstanceOf(ProductEntity::class, $product);
120-
121-
return $product;
122-
}
123-
124-
private function upsertProductWithRelationCleanup(ProductBuilder $builder): void
178+
private function upsertProductWithRelationCleanup(array $payload): void
125179
{
126-
$payload = $builder->build();
127-
128180
$payload['pricesCleanupRelations'] = true;
129181
$payload['categoriesCleanupRelations'] = true;
130182

131-
$this->executeUpsert('product', $payload);
183+
$this->upsertProduct($payload);
132184
}
133185
}

0 commit comments

Comments
 (0)