Skip to content

Commit 89a1e2a

Browse files
committed
Added container values serialization
1 parent b26eded commit 89a1e2a

File tree

4 files changed

+197
-9
lines changed

4 files changed

+197
-9
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ This package's only purpose is to build custom repeated layout components, such
1616
- `build($data)`
1717
- `buildUsing($callback)`
1818
- `insert($key, $attributes, $index, $id)`
19+
- serializing the flexible container's state
20+
- `serialize($resource, $attribute)`
21+
- `serializeAs($format, $resource, $attribute)`
22+
- `serializeUsingFormat($format)`
23+
- `serializeUsing($callback)`
1924
- get all inserted instances, and manipulate the LayoutCollection :
2025
- `instances()`
2126
- `$instances->find($key)`

src/Concerns/HasResolver.php

Lines changed: 88 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace Whitecube\LaravelFlexibleContent\Concerns;
44

55
use Illuminate\Support\Collection;
6+
use Whitecube\LaravelFlexibleContent\Contracts\Layout;
7+
use Whitecube\LaravelFlexibleContent\Exceptions\InvalidSerializationFormatException;
68

79
trait HasResolver
810
{
@@ -14,11 +16,19 @@ trait HasResolver
1416
public $buildCallback;
1517

1618
/**
17-
* The callback to be used to save the Flexible container's value.
19+
* The callback to be used when saving the Flexible container's value.
1820
*
1921
* @var null|callable
2022
*/
21-
public $saveCallback;
23+
public $serializeCallback;
24+
25+
/**
26+
* The value serialization method.
27+
* Available methods are: json, array, collection
28+
*
29+
* @var string
30+
*/
31+
protected $serializeFormat = 'json';
2232

2333
/**
2434
* Define the callback that should be used to setup the Flexible container's value.
@@ -34,14 +44,27 @@ public function buildUsing(callable $buildCallback)
3444
}
3545

3646
/**
37-
* Define the callback that should be used to save the Flexible container's value.
47+
* Define the callback that should be used when saving the Flexible container's value.
3848
*
3949
* @param callable $saveCallback
4050
* @return $this
4151
*/
42-
public function saveUsing(callable $saveCallback)
52+
public function serializeUsing(callable $serializeCallback)
53+
{
54+
$this->serializeCallback = $serializeCallback;
55+
56+
return $this;
57+
}
58+
59+
/**
60+
* Define a default serialization format method that should be used when saving the Flexible container's value.
61+
*
62+
* @param string $serializeFormat
63+
* @return $this
64+
*/
65+
public function serializeUsingFormat(string $serializeFormat)
4366
{
44-
$this->saveCallback = $saveCallback;
67+
$this->serializeFormat = $serializeFormat;
4568

4669
return $this;
4770
}
@@ -111,11 +134,67 @@ public function buildItem($item)
111134
/**
112135
* Execute what has to be done in order to save the current value for next build.
113136
*
114-
* @return $this
137+
* @return mixed
115138
*/
116-
public function save()
139+
public function serialize()
117140
{
118-
// TODO.
119-
return $this;
141+
if(! is_null($this->serializeCallback)) {
142+
return call_user_func($this->serializeCallback, $this);
143+
}
144+
145+
return $this->serializeAs($this->serializeFormat);
146+
}
147+
148+
/**
149+
* Transform the current value in the desired format.
150+
*
151+
* @param string $format
152+
* @return mixed
153+
*/
154+
public function serializeAs(string $format)
155+
{
156+
$serializationMethod = 'serializeAs' . ucfirst($format);
157+
158+
if(! method_exists($this, $serializationMethod)) {
159+
throw InvalidSerializationFormatException::make($format);
160+
}
161+
162+
return $this->$serializationMethod();
163+
}
164+
165+
/**
166+
* Transform the current value into a serialized array.
167+
*
168+
* @return array
169+
*/
170+
public function serializeAsArray()
171+
{
172+
return $this->instances()
173+
->map(fn(Layout $instance) => [
174+
'key' => $instance->getKey(),
175+
'id' => $instance->getId(),
176+
'attributes' => $instance->getAttributes()
177+
])
178+
->all();
179+
}
180+
181+
/**
182+
* Transform the current value into a serialized JSON string.
183+
*
184+
* @return string
185+
*/
186+
public function serializeAsJson()
187+
{
188+
return json_encode($this->serializeAsArray());
189+
}
190+
191+
/**
192+
* Transform the current value into a serialized collection.
193+
*
194+
* @return \Illuminate\Support\Collection
195+
*/
196+
public function serializeAsCollection()
197+
{
198+
return collect($this->serializeAsArray());
120199
}
121200
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Whitecube\LaravelFlexibleContent\Exceptions;
4+
5+
use InvalidArgumentException;
6+
7+
class InvalidSerializationFormatException extends InvalidArgumentException
8+
{
9+
/**
10+
* Create a new exception instance with given arguments
11+
*
12+
* @param string $format
13+
* @return \InvalidArgumentException
14+
*/
15+
static public function make($format) : InvalidArgumentException
16+
{
17+
return new static('Could not save flexible as "' . $format . '": method "serializeAs' . ucfirst($format) . '" is undefined.');
18+
}
19+
}

tests/Unit/InstanceResolvingTest.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Tests\Unit;
44

5+
use Illuminate\Support\Collection;
56
use Whitecube\LaravelFlexibleContent\Flexible;
67

78
it('can build instances from serialized data (array)', function() {
@@ -84,3 +85,87 @@
8485

8586
expect($values->implode(','))->toBe('one!,two!,three!');
8687
});
88+
89+
it('can serialize instances into an array', function() {
90+
$serialized = (new Flexible())
91+
->register(fn ($layout) => $layout->key('foo'))
92+
->register(fn ($layout) => $layout->key('bar'))
93+
->insert('foo', ['test' => 0])
94+
->insert('bar', ['test' => 1])
95+
->insert('foo', ['test' => 2])
96+
->serializeAsArray();
97+
98+
expect($serialized)->toBeArray();
99+
100+
foreach (['foo', 'bar', 'foo'] as $index => $key) {
101+
expect($serialized[$index]['key'] ?? null)->toBe($key);
102+
expect($serialized[$index]['id'] ?? null)->toBeString();
103+
expect($serialized[$index]['attributes']['test'] ?? null)->toBe($index);
104+
}
105+
});
106+
107+
it('can serialize instances into a JSON string', function() {
108+
$serialized = (new Flexible())
109+
->register(fn ($layout) => $layout->key('foo'))
110+
->register(fn ($layout) => $layout->key('bar'))
111+
->insert('foo', ['test' => 0])
112+
->insert('bar', ['test' => 1])
113+
->insert('foo', ['test' => 2])
114+
->serializeAsJson();
115+
116+
expect($serialized)->toBeString();
117+
expect($serialized = json_decode($serialized, true))->toBeArray();
118+
119+
foreach (['foo', 'bar', 'foo'] as $index => $key) {
120+
expect($serialized[$index]['key'] ?? null)->toBe($key);
121+
expect($serialized[$index]['id'] ?? null)->toBeString();
122+
expect($serialized[$index]['attributes']['test'] ?? null)->toBe($index);
123+
}
124+
});
125+
126+
it('can serialize instances into a collection', function() {
127+
$serialized = (new Flexible())
128+
->register(fn ($layout) => $layout->key('foo'))
129+
->register(fn ($layout) => $layout->key('bar'))
130+
->insert('foo', ['test' => 0])
131+
->insert('bar', ['test' => 1])
132+
->insert('foo', ['test' => 2])
133+
->serializeAsCollection();
134+
135+
expect($serialized)->toBeInstanceOf(Collection::class);
136+
137+
foreach (['foo', 'bar', 'foo'] as $index => $key) {
138+
expect($serialized->get($index)['key'] ?? null)->toBe($key);
139+
expect($serialized->get($index)['id'] ?? null)->toBeString();
140+
expect($serialized->get($index)['attributes']['test'] ?? null)->toBe($index);
141+
}
142+
});
143+
144+
it('can serialize instances into a default (configurable) format', function() {
145+
$flexible = (new Flexible())
146+
->register(fn ($layout) => $layout->key('foo'))
147+
->register(fn ($layout) => $layout->key('bar'))
148+
->insert('foo', ['test' => 0])
149+
->insert('bar', ['test' => 1])
150+
->insert('foo', ['test' => 2]);
151+
152+
expect($flexible->serialize())->toBeString();
153+
154+
$flexible->serializeUsingFormat('array');
155+
156+
expect($flexible->serialize())->toBeArray();
157+
});
158+
159+
it('can serialize instances using a custom callable', function() {
160+
$flexible = (new Flexible())
161+
->register(fn ($layout) => $layout->key('foo'))
162+
->register(fn ($layout) => $layout->key('bar'))
163+
->insert('foo', ['test' => 0])
164+
->insert('bar', ['test' => 1])
165+
->insert('foo', ['test' => 2])
166+
->serializeUsing(function(Flexible $flexible) {
167+
return $flexible->instances()->map(fn($instance) => $instance->getKey() . $instance->getAttributes()['test'])->implode(',');
168+
});
169+
170+
expect($flexible->serialize())->toBe('foo0,bar1,foo2');
171+
})->only();

0 commit comments

Comments
 (0)