Skip to content

Commit

Permalink
Add serialization and conversion from string
Browse files Browse the repository at this point in the history
  • Loading branch information
avvertix committed Oct 14, 2024
1 parent d7e8250 commit 7aa4673
Show file tree
Hide file tree
Showing 2 changed files with 237 additions and 3 deletions.
60 changes: 57 additions & 3 deletions src/DocumentFormat/DocumentNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
namespace OneOffTech\Parse\Client\DocumentFormat;

use Countable;
use JsonSerializable;
use OneOffTech\Parse\Client\Exceptions\EmptyDocumentException;
use OneOffTech\Parse\Client\Exceptions\InvalidDocumentFormatException;
use RecursiveArrayIterator;
use RecursiveIteratorIterator;
use ReturnTypeWillChange;

class DocumentNode implements Countable
class DocumentNode implements Countable, JsonSerializable
{
public function __construct(
public readonly array $content,
Expand Down Expand Up @@ -42,7 +44,7 @@ public function isEmpty(): bool
public function hasContent(): bool
{
foreach (new RecursiveIteratorIterator(new RecursiveArrayIterator($this->content), RecursiveIteratorIterator::LEAVES_ONLY) as $key => $value) {
if ($key === 'text' && ! empty($value)) {
if (($key === 'text' || $key === 'content') && ! empty($value)) {
return true;
}
}
Expand All @@ -65,7 +67,7 @@ public function text(): string
$text = [];

foreach (new RecursiveIteratorIterator(new RecursiveArrayIterator($this->content), RecursiveIteratorIterator::LEAVES_ONLY) as $key => $value) {
if ($key === 'text' && ! empty($value)) {
if (($key === 'text' || $key === 'content') && ! empty($value)) {
$text[] = $value;
}
}
Expand All @@ -87,6 +89,33 @@ public function throwIfNoContent(): self
return $this;
}

/**
* Return an array representation of the document node
*/
public function toArray(): array
{
return [
'category' => 'doc',
'attributes' => null,
'content' => $this->content
];
}

/**
* Return a JSON serialization of the document node
*/
public function toJson(): string
{
return json_encode($this);
}

#[ReturnTypeWillChange]
public function jsonSerialize(): mixed
{
return $this->toArray();
}


/**
* Create a document node from associative array
*/
Expand All @@ -106,4 +135,29 @@ public static function fromArray(array $data): DocumentNode

return new DocumentNode($data['content'] ?? [], $data['attributes'] ?? []);
}

public static function fromString(string $data): DocumentNode
{
return static::fromArray([
'category' => 'doc',
'attributes' => null,
'content' => [
[
'category' => 'page',
'attributes' => [
'page' => 1,
],
'content' => [
[
'role' => 'body',
'category' => 'text',
'content' => $data,
'marks' => [],
'attributes' => [],
]
]
]
]
]);
}
}
180 changes: 180 additions & 0 deletions tests/DocumentNodeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
<?php

use OneOffTech\Parse\Client\DocumentFormat\DocumentNode;
use OneOffTech\Parse\Client\Exceptions\EmptyDocumentException;
use OneOffTech\Parse\Client\Exceptions\InvalidDocumentFormatException;

test('node created from string', function () {

$document = DocumentNode::fromString('test content');

expect($document)
->toBeInstanceOf(DocumentNode::class)
->toHaveCount(1);

expect($document->hasContent())
->toBeTrue();

expect($document->isEmpty())
->toBeFalse();

expect($document->text())
->toBeString()->toEqual('test content');

$pages = $document->pages();

expect($pages)
->toHaveCount(1);

});

test('node created from array', function () {
$document = DocumentNode::fromArray([
'category' => 'doc',
'attributes' => null,
'content' => [
[
'category' => 'page',
'attributes' => [
'page' => 1,
],
'content' => [
[
'role' => 'body',
'category' => 'text',
'content' => 'This is the page one text',
'marks' => [],
'attributes' => [],
]
]
]
]
]);

expect($document)
->toBeInstanceOf(DocumentNode::class)
->toHaveCount(1);

expect($document->isEmpty())
->toBeFalse();

expect($document->hasContent())
->toBeTrue();

expect($document->text())
->toBeString()->toEqual('This is the page one text');

$pages = $document->pages();

expect($pages)
->toHaveCount(1);

});

test('throws if empty document', function () {
DocumentNode::fromString('')->throwIfNoContent();
})->throws(EmptyDocumentException::class, 'Document has no textual content.');

test('throws if missing category', function () {
DocumentNode::fromArray([
'attributes' => null,
'content' => [
[
'category' => 'page',
'attributes' => [
'page' => 1,
],
'content' => [
[
'role' => 'body',
'category' => 'text',
'content' => 'This is the page one text',
'marks' => [],
'attributes' => [],
]
]
]
]
]);

})->throws(InvalidDocumentFormatException::class, 'Unexpected document structure. Missing category or content.');

test('throws if missing content', function () {
DocumentNode::fromArray([
'category' => 'doc',
'attributes' => null,
]);

})->throws(InvalidDocumentFormatException::class, 'Unexpected document structure. Missing category or content.');

test('throws if category is not doc', function () {
DocumentNode::fromArray([
'category' => 'something',
'attributes' => null,
'content' => [
[
'category' => 'page',
'attributes' => [
'page' => 1,
],
'content' => [
[
'role' => 'body',
'category' => 'text',
'content' => 'This is the page one text',
'marks' => [],
'attributes' => [],
]
]
]
]
]);

})->throws(InvalidDocumentFormatException::class, 'Unexpected node category. Expecting [doc] found [something].');

test('throws if content is not an array', function () {
DocumentNode::fromArray([
'category' => 'doc',
'attributes' => null,
'content' => 'a string'
]);

})->throws(InvalidDocumentFormatException::class, 'Unexpected content format. Expecting [array].');


test('can be serialized in json', function () {

$expectedContent = [
'category' => 'doc',
'attributes' => null,
'content' => [
[
'category' => 'page',
'attributes' => [
'page' => 1,
],
'content' => [
[
'role' => 'body',
'category' => 'text',
'content' => 'This is the page one text',
'marks' => [],
'attributes' => [],
]
]
]
]
];

$document = DocumentNode::fromArray($expectedContent);

expect($document->toArray())
->toEqual($expectedContent);

expect($document->toJson())
->toEqual(json_encode($expectedContent));

expect(json_encode($document))
->toEqual(json_encode($expectedContent));

});

0 comments on commit 7aa4673

Please sign in to comment.