Skip to content

Commit 02e347a

Browse files
authored
Extend serialization to provide a merge strategy for a custom serialization (#6)
1 parent 478f53d commit 02e347a

File tree

4 files changed

+138
-16
lines changed

4 files changed

+138
-16
lines changed

src/Exception/Object/InvalidAdditionalPropertiesException.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public function __construct($providedValue, string $propertyName, $nestedExcepti
3535

3636
/**
3737
* Get a list of nested exceptions containing all failed validations indexed by the property name
38-
38+
*
3939
* @return ValidationException[][]
4040
*/
4141
public function getNestedExceptions(): array
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace PHPModelGenerator\Exception\Object;
6+
7+
use PHPModelGenerator\Exception\ValidationException;
8+
9+
/**
10+
* Class RegularPropertyAsAdditionalPropertyException
11+
*
12+
* @package PHPModelGenerator\Exception\Object
13+
*/
14+
class RegularPropertyAsAdditionalPropertyException extends ValidationException
15+
{
16+
/**
17+
* @var string
18+
*/
19+
private $class;
20+
21+
/**
22+
* EnumException constructor.
23+
*
24+
* @param $providedValue
25+
* @param string $propertyName
26+
* @param string $class
27+
*/
28+
public function __construct($providedValue, string $propertyName, string $class)
29+
{
30+
$this->class = $class;
31+
32+
parent::__construct(
33+
sprintf("Couldn't add regular property %s as additional property to object %s", $propertyName, $class),
34+
$propertyName,
35+
$providedValue
36+
);
37+
}
38+
39+
/**
40+
* @return string
41+
*/
42+
public function getClass(): string
43+
{
44+
return $this->class;
45+
}
46+
}

src/Model/SerializedValue.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace PHPModelGenerator\Model;
6+
7+
use Exception;
8+
9+
class SerializedValue
10+
{
11+
// simply add the provided value under the property key
12+
public const STRATEGY_ADD_VALUE = 0;
13+
// merge the provided value into the serialization result
14+
public const STRATEGY_MERGE_VALUE = 1;
15+
16+
/** @var mixed */
17+
protected $serializedValue;
18+
/** @var int */
19+
protected $serializationStrategy;
20+
21+
public function __construct($serializedValue, int $serializationStrategy = self::STRATEGY_ADD_VALUE)
22+
{
23+
if (!is_array($serializedValue) && $serializationStrategy === self::STRATEGY_MERGE_VALUE) {
24+
throw new Exception("Can't merge a non-array value into serialization result");
25+
}
26+
27+
$this->serializedValue = $serializedValue;
28+
$this->serializationStrategy = $serializationStrategy;
29+
}
30+
31+
/**
32+
* @return mixed
33+
*/
34+
public function getSerializedValue()
35+
{
36+
return $this->serializedValue;
37+
}
38+
39+
/**
40+
* @return int
41+
*/
42+
public function getSerializationStrategy(): int
43+
{
44+
return $this->serializationStrategy;
45+
}
46+
}

src/Traits/SerializableTrait.php

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace PHPModelGenerator\Traits;
66

7+
use PHPModelGenerator\Model\SerializedValue;
8+
79
/**
810
* Provide methods to serialize generated models
911
*
@@ -13,6 +15,8 @@
1315
*/
1416
trait SerializableTrait
1517
{
18+
private static $customSerializer = [];
19+
1620
/**
1721
* Get a JSON representation of the current state
1822
*
@@ -32,6 +36,14 @@ public function toJSON(array $except = [], int $options = 0, int $depth = 512)
3236
return json_encode($this->toArray($except, $depth), $options, $depth);
3337
}
3438

39+
/**
40+
* Return a JSON serializable representation of the current state
41+
*/
42+
public function jsonSerialize()
43+
{
44+
return $this->toArray();
45+
}
46+
3547
/**
3648
* Get an array representation of the current state
3749
*
@@ -56,27 +68,40 @@ public function toArray(array $except = [], int $depth = 512)
5668
continue;
5769
}
5870

71+
if ($customSerializer = $this->getCustomSerializerMethod($key)) {
72+
$this->handleSerializedValue($modelData, $key, $this->{$customSerializer}());
73+
continue;
74+
}
75+
5976
if (is_array($value)) {
6077
$subData = [];
6178
foreach ($value as $subKey => $element) {
62-
$subData[$subKey] = $this->evaluateAttribute($key, $element, $depth, $except);
79+
$subData[$subKey] = $this->evaluateAttribute($element, $depth, $except);
6380
}
6481
$modelData[$key] = $subData;
6582
} else {
66-
$modelData[$key] = $this->evaluateAttribute($key, $value, $depth, $except);
83+
$modelData[$key] = $this->evaluateAttribute($value, $depth, $except);
6784
}
6885
}
6986

7087
return $modelData;
7188
}
7289

73-
private function evaluateAttribute(string $property, $attribute, int $depth, array $except)
90+
private function handleSerializedValue(array &$data, $key, $serializedValue): void
7491
{
75-
$customSerializer = 'serialize' . ucfirst($property);
76-
if (method_exists($this, $customSerializer)) {
77-
return $this->{$customSerializer}();
92+
if ($serializedValue instanceof SerializedValue &&
93+
$serializedValue->getSerializationStrategy() === SerializedValue::STRATEGY_MERGE_VALUE
94+
) {
95+
$data = array_merge($data, $serializedValue->getSerializedValue());
96+
97+
return;
7898
}
7999

100+
$data[$key] = $serializedValue;
101+
}
102+
103+
private function evaluateAttribute($attribute, int $depth, array $except)
104+
{
80105
if (!is_object($attribute)) {
81106
return $attribute;
82107
}
@@ -88,17 +113,22 @@ private function evaluateAttribute(string $property, $attribute, int $depth, arr
88113
return (0 >= $depth)
89114
? null
90115
: (
91-
method_exists($attribute, 'toArray')
92-
? $attribute->toArray($except, $depth - 1)
93-
: get_object_vars($attribute)
116+
method_exists($attribute, 'toArray')
117+
? $attribute->toArray($except, $depth - 1)
118+
: get_object_vars($attribute)
94119
);
95120
}
96121

97-
/**
98-
* Return a JSON serializable representation of the current state
99-
*/
100-
public function jsonSerialize()
101-
{
102-
return $this->toArray();
122+
private function getCustomSerializerMethod(string $property) {
123+
if (isset(self::$customSerializer[$property])) {
124+
return self::$customSerializer[$property];
125+
}
126+
127+
$customSerializer = 'serialize' . ucfirst($property);
128+
if (!method_exists($this, $customSerializer)) {
129+
$customSerializer = false;
130+
}
131+
132+
return self::$customSerializer[$property] = $customSerializer;
103133
}
104134
}

0 commit comments

Comments
 (0)