Skip to content

Commit

Permalink
Merge pull request #545 from netglue/shared-slices
Browse files Browse the repository at this point in the history
Support Shared Slice Properties
  • Loading branch information
gsteel authored Oct 31, 2024
2 parents 9f04559 + 9147136 commit bc52738
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 11 deletions.
23 changes: 21 additions & 2 deletions src/Document/Fragment/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use function is_int;
use function is_object;
use function is_scalar;
use function is_string;
use function preg_match;
use function property_exists;
use function strpos;
Expand Down Expand Up @@ -251,9 +252,27 @@ private static function sliceFactory(object $data): Fragment
return self::factory($value);
}, $primary));

$type = self::assertObjectPropertyIsNonEmptyString($data, 'slice_type');
$label = self::optionalNonEmptyStringProperty($data, 'slice_label');
$variation = self::optionalStringProperty($data, 'variation');
$version = self::optionalNonEmptyStringProperty($data, 'version');
$id = self::optionalNonEmptyStringProperty($data, 'id');

if (is_string($id) && is_string($variation)) {
return Slice::shared(
$type,
$label,
$primary,
$items,
$variation,
$version,
$id,
);
}

return Slice::new(
self::assertObjectPropertyIsString($data, 'slice_type'),
self::optionalStringProperty($data, 'slice_label'),
$type,
$label,
$primary,
$items,
);
Expand Down
57 changes: 52 additions & 5 deletions src/Document/Fragment/Slice.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,59 @@

final class Slice implements Fragment, Stringable
{
/**
* @param non-empty-string $type
* @param non-empty-string|null $label
* @param non-empty-string|null $id
*/
private function __construct(
private string $type,
private string|null $label,
private FragmentCollection $primary,
private FragmentCollection $items,
private readonly string $type,
private readonly string|null $label,
private readonly FragmentCollection $primary,
private readonly FragmentCollection $items,
private readonly string|null $variation,
private readonly string|null $version,
private readonly string|null $id,
) {
}

/**
* @param non-empty-string $type
* @param non-empty-string|null $label
*/
public static function new(
string $type,
string|null $label,
FragmentCollection $primary,
FragmentCollection $items,
): self {
return new self($type, $label, $primary, $items);
return new self($type, $label, $primary, $items, null, null, null);
}

/**
* @param non-empty-string $type
* @param non-empty-string|null $label
* @param non-empty-string $id
*/
public static function shared(
string $type,
string|null $label,
FragmentCollection $primary,
FragmentCollection $items,
string $variation,
string|null $version,
string $id,
): self {
return new self($type, $label, $primary, $items, $variation, $version, $id);
}

/** @return non-empty-string */
public function type(): string
{
return $this->type;
}

/** @return non-empty-string|null */
public function label(): string|null
{
return $this->label;
Expand All @@ -52,6 +83,22 @@ public function items(): FragmentCollection
return $this->items;
}

public function variation(): string|null
{
return $this->variation;
}

public function version(): string|null
{
return $this->version;
}

/** @return non-empty-string|null */
public function id(): string|null
{
return $this->id;
}

public function isEmpty(): bool
{
return $this->primary->isEmpty() && $this->items->isEmpty();
Expand Down
21 changes: 21 additions & 0 deletions src/Value/DataAssertionBehaviour.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ private static function assertObjectPropertyIsString(object $object, string $pro
return $value;
}

/** @return non-empty-string */
private static function assertObjectPropertyIsNonEmptyString(object $object, string $property): string
{
self::assertPropertyExists($object, $property);
$value = $object->{$property};
if (! is_string($value) || $value === '') {
throw UnexpectedValue::withInvalidPropertyType($object, $property, 'non-empty-string');
}

return $value;
}

private static function assertObjectPropertyIsInteger(object $object, string $property): int
{
self::assertPropertyExists($object, $property);
Expand Down Expand Up @@ -139,6 +151,15 @@ private static function optionalStringProperty(object $object, string $property)
return $value;
}

/** @return non-empty-string|null */
private static function optionalNonEmptyStringProperty(object $object, string $property): string|null
{
$value = self::optionalStringProperty($object, $property);
assert($value !== '');

return $value;
}

/** @return mixed[]|null */
private static function optionalArrayProperty(object $object, string $property): array|null
{
Expand Down
32 changes: 32 additions & 0 deletions test/Unit/Document/Fragment/FactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -292,4 +292,36 @@ public function testAMediaLinkWithNonNumericSizeIsExceptional(): void

Factory::factory($data);
}

public function testSlicesMustProvideANonEmptySliceType(): void
{
$data = Json::decodeObject('{
"slice_type": "",
"items":[],
"primary":{}
}');

$this->expectException(UnexpectedValue::class);
$this->expectExceptionMessage('Expected the object property "slice_type" to be a non-empty-string');

Factory::factory($data);
}

public function testSharedSlicesMayHaveAnEmptyVersion(): void
{
$data = Json::decodeObject('{
"slice_type": "foo",
"items":[],
"primary":{},
"id":"bar",
"version":"",
"variation":""
}');

$slice = Factory::factory($data);
self::assertInstanceOf(Fragment\Slice::class, $slice);

self::assertNull($slice->version());
self::assertNull($slice->variation());
}
}
55 changes: 51 additions & 4 deletions test/Unit/Document/Fragment/SliceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace PrismicTest\Document\Fragment;

use PHPUnit\Framework\Attributes\Depends;
use Prismic\Document\Fragment\Slice;
use Prismic\Document\FragmentCollection;
use Prismic\Json;
Expand Down Expand Up @@ -47,25 +48,47 @@ public function testThatAnEmptySliceCanBeFound(): Slice
return $slice;
}

/** @depends testThatASliceCanBeFound */
public function testThatASharedSliceCanBeFound(): Slice
{
self::assertInstanceOf(FragmentCollection::class, $this->slices);
$slice = $this->slices->filter(static function (Slice $slice): bool {
return $slice->type() === 'shared_slice';
})->first();
self::assertInstanceOf(Slice::class, $slice);

return $slice;
}

public function testThatASharedSliceCanBeFoundWithAnEmptyVersionString(): Slice
{
self::assertInstanceOf(FragmentCollection::class, $this->slices);
$slice = $this->slices->filter(static function (Slice $slice): bool {
return $slice->type() === 'shared_slice_empty_version';
})->first();
self::assertInstanceOf(Slice::class, $slice);

return $slice;
}

#[Depends('testThatASliceCanBeFound')]
public function testThatTheLabelIsTheExpectedValue(Slice $slice): void
{
self::assertEquals('custom-label', $slice->label());
}

/** @depends testThatASliceCanBeFound */
#[Depends('testThatASliceCanBeFound')]
public function testThatTheSliceIsNotEmpty(Slice $slice): void
{
self::assertFalse($slice->isEmpty());
}

/** @depends testThatAnEmptySliceCanBeFound */
#[Depends('testThatAnEmptySliceCanBeFound')]
public function testThatTheEmptySliceIsEmpty(Slice $slice): void
{
self::assertTrue($slice->isEmpty());
}

/** @depends testThatASliceCanBeFound */
#[Depends('testThatASliceCanBeFound')]
public function testThatToStringWillYieldTheExpectedValue(Slice $slice): void
{
$expect = <<<'TEXT'
Expand All @@ -85,4 +108,28 @@ public function testThatTheEmptySliceIsAnEmptyStringWhenCastToAString(Slice $sli
{
self::assertEquals('', (string) $slice);
}

#[Depends('testThatASliceCanBeFound')]
public function testSharedSlicePropertiesAreNullForRegularSlices(Slice $slice): void
{
self::assertNull($slice->id());
self::assertNull($slice->variation());
self::assertNull($slice->version());
}

#[Depends('testThatASharedSliceCanBeFound')]
public function testSharedSlicesHaveAdditionalProperties(Slice $slice): void
{
self::assertNotEmpty($slice->id());
self::assertNotEmpty($slice->variation());
self::assertNotEmpty($slice->version());
}

#[Depends('testThatASharedSliceCanBeFoundWithAnEmptyVersionString')]
public function testSliceWithEmptyVersionWillHaveNullVersion(Slice $slice): void
{
self::assertNotEmpty($slice->id());
self::assertNotEmpty($slice->variation());
self::assertNull($slice->version());
}
}
22 changes: 22 additions & 0 deletions test/fixture/basic-slices.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,28 @@
"slice_label": null,
"items": [],
"primary": {}
},
{
"slice_type": "shared_slice",
"slice_label": null,
"id": "shared_slice$62db7b7f-1191-41b4-833f-cee6d499d82e",
"variation": "default",
"version": "123",
"items": [ ],
"primary": {
"text": 1
}
},
{
"slice_type": "shared_slice_empty_version",
"slice_label": null,
"id": "shared_slice_empty_version$62db7b7f-1191-41b4-833f-cee6d499d82e",
"variation": "default",
"version": "",
"items": [ ],
"primary": {
"text": 1
}
}
]
}
Expand Down

0 comments on commit bc52738

Please sign in to comment.