Skip to content

Commit

Permalink
TASK: Make sure unset properties never leak into the node
Browse files Browse the repository at this point in the history
The Node's properties must not reflect that a node's property was unset once.
  • Loading branch information
mhsdesign committed Feb 3, 2024
1 parent 4892292 commit 721fb45
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ public function merge(self $other): self

public function withoutUnsets(): self
{
if (!in_array(UnsetPropertyValue::get(), $this->values, true)) {
return $this;
}
$values = [];
foreach ($this->values as $name => $serializedValue) {
if ($serializedValue instanceof UnsetPropertyValue) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ public function __construct(
SerializedPropertyValues $serializedPropertyValues,
PropertyConverter $propertyConverter
) {
$this->serializedPropertyValues = $serializedPropertyValues;
// we are not interested in the unset properties, as for the read model we make no difference between unset and never set.
// the projection should not need to preserve unset properties, but if it does, we filter them here.
$this->serializedPropertyValues = $serializedPropertyValues->withoutUnsets();
$this->propertyConverter = $propertyConverter;
}

Expand All @@ -62,7 +64,8 @@ public function offsetGet($offset): mixed
}

$serializedProperty = $this->serializedPropertyValues->getProperty($offset);
if ($serializedProperty === null || $serializedProperty instanceof UnsetPropertyValue) {
assert(!$serializedProperty instanceof UnsetPropertyValue); // not possible, see withoutUnsets
if ($serializedProperty === null) {
return null;
}
return $this->deserializedPropertyValuesRuntimeCache[$offset] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,17 @@ public function getPlainValuesReturnsNullForUnsetValues(): void
*/
public function withoutUnsets(): void
{
// the format which is implicitly used in the event log, due to json_serialize
// the format which should be used by the projections
$propertyValues = SerializedPropertyValues::fromArray(['someProperty' => UnsetPropertyValue::get(), 'otherProperty' => SerializedPropertyValue::create('text', 'string'), 'reputation' => UnsetPropertyValue::get()]);
self::assertEquals(
SerializedPropertyValues::fromArray(['otherProperty' => SerializedPropertyValue::create('text', 'string')]),
$propertyValues->withoutUnsets()
);
}

$propertyValues = SerializedPropertyValues::fromArray(['someProperty' => SerializedPropertyValue::create('text', 'string'), 'otherProperty' => SerializedPropertyValue::create('text', 'string')]);
self::assertEquals(
$propertyValues,
$propertyValues->withoutUnsets()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public function offsetGetReturnsNullIfPropertyDoesNotExist(): void
$this->mockSerializer->expects($this->never())->method($this->anything());
$collection = new PropertyCollection(SerializedPropertyValues::fromArray(['someProperty' => ['value' => 'some string', 'type' => 'string']]), $this->mockPropertyConverter);
self::assertNull($collection['non-existing']);
self::assertFalse(isset($collection['non-existing']));
}

/**
Expand All @@ -58,6 +59,7 @@ public function offsetGetReturnsNullIfSerializedPropertyValueIsNull(): void
$this->mockSerializer->expects($this->never())->method($this->anything());
$collection = new PropertyCollection(SerializedPropertyValues::fromArray(['someProperty' => null]), $this->mockPropertyConverter);
self::assertNull($collection['someProperty']);
self::assertFalse(isset($collection['someProperty']));
}

/**
Expand All @@ -68,6 +70,7 @@ public function offsetGetReturnsDeserializedValue(): void
$this->mockSerializer->expects($this->once())->method('denormalize')->with('some string', 'string', null, [])->willReturn('some deserialized value');
$collection = new PropertyCollection(SerializedPropertyValues::fromArray(['someProperty' => ['value' => 'some string', 'type' => 'string']]), $this->mockPropertyConverter);
self::assertSame('some deserialized value', $collection['someProperty']);
self::assertTrue(isset($collection['someProperty']));
}

/**
Expand Down Expand Up @@ -107,7 +110,19 @@ public function serializedReturnsSerializedPropertyValues(): void
{
$serializedPropertyValues = SerializedPropertyValues::fromArray(['someProperty' => ['value' => 'some string', 'type' => 'string']]);
$collection = new PropertyCollection($serializedPropertyValues, $this->mockPropertyConverter);
self::assertSame($serializedPropertyValues, $collection->serialized());
self::assertEquals($serializedPropertyValues, $collection->serialized());
}

/**
* @test
*/
public function serializedReturnsSerializedPropertyWithoutUnsetValues(): void
{
$serializedPropertyValues = SerializedPropertyValues::fromArray(['unsetProperty' => null, 'someProperty' => ['value' => 'some string', 'type' => 'string']]);
$collection = new PropertyCollection($serializedPropertyValues, $this->mockPropertyConverter);
self::assertEquals(
SerializedPropertyValues::fromArray(['someProperty' => ['value' => 'some string', 'type' => 'string']]),
$collection->serialized()
);
}
}

0 comments on commit 721fb45

Please sign in to comment.