Skip to content

Commit 9569a68

Browse files
authored
Replace abandoned spatie/data-transfer-object with own DTO implementation (#1024)
1 parent 0b578d1 commit 9569a68

File tree

5 files changed

+104
-13
lines changed

5 files changed

+104
-13
lines changed

camel/BaseDTO.php

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,85 @@
33
namespace Knuckles\Camel;
44

55
use Illuminate\Contracts\Support\Arrayable;
6-
use Spatie\DataTransferObject\DataTransferObject;
76

87

9-
class BaseDTO extends DataTransferObject implements Arrayable, \ArrayAccess
8+
class BaseDTO implements Arrayable, \ArrayAccess
109
{
1110
/**
1211
* @var array $custom
1312
* Added so end-users can dynamically add additional properties for their own use.
1413
*/
1514
public array $custom = [];
1615

16+
public function __construct(array $parameters = [])
17+
{
18+
// Initialize all properties to their default values first
19+
$this->initializeProperties();
20+
21+
foreach ($parameters as $key => $value) {
22+
if (property_exists($this, $key)) {
23+
$this->$key = $this->castProperty($key, $value);
24+
}
25+
}
26+
}
27+
28+
protected function initializeProperties(): void
29+
{
30+
$reflection = new \ReflectionClass($this);
31+
32+
foreach ($reflection->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
33+
$name = $property->getName();
34+
35+
// Skip if already initialized (has a default value)
36+
if ($property->hasDefaultValue()) {
37+
continue;
38+
}
39+
40+
$type = $property->getType();
41+
if ($type && $type->allowsNull()) {
42+
$this->$name = null;
43+
}
44+
}
45+
}
46+
47+
protected function castProperty(string $key, mixed $value): mixed
48+
{
49+
// If the value is already the correct type, return it as-is
50+
if (!is_array($value)) {
51+
return $value;
52+
}
53+
54+
// Get property type through reflection
55+
$reflection = new \ReflectionClass($this);
56+
if (!$reflection->hasProperty($key)) {
57+
return $value;
58+
}
59+
60+
$property = $reflection->getProperty($key);
61+
$type = $property->getType();
62+
63+
if ($type && $type instanceof \ReflectionNamedType && !$type->isBuiltin()) {
64+
$className = $type->getName();
65+
66+
// If it's a DTO class in our namespace, instantiate it
67+
if (class_exists($className) && is_subclass_of($className, self::class)) {
68+
return new $className($value);
69+
}
70+
71+
// If it's another class in our namespace that has a constructor accepting arrays
72+
if (class_exists($className)) {
73+
try {
74+
return new $className($value);
75+
} catch (\Throwable $e) {
76+
// If instantiation fails, return the original value
77+
return $value;
78+
}
79+
}
80+
}
81+
82+
return $value;
83+
}
84+
1785
public static function create(BaseDTO|array $data, BaseDTO|array $inheritFrom = []): static
1886
{
1987
if ($data instanceof static) {
@@ -49,6 +117,15 @@ protected function parseArray(array $array): array
49117
return $array;
50118
}
51119

120+
public function toArray(): array
121+
{
122+
$array = [];
123+
foreach (get_object_vars($this) as $property => $value) {
124+
$array[$property] = $value;
125+
}
126+
return $this->parseArray($array);
127+
}
128+
52129
public static function make(array|self $data): static
53130
{
54131
return $data instanceof static ? $data : new static($data);
@@ -73,4 +150,22 @@ public function offsetUnset(mixed $offset): void
73150
{
74151
unset($this->$offset);
75152
}
153+
154+
public function except(string ...$keys): array
155+
{
156+
$array = [];
157+
foreach (get_object_vars($this) as $property => $value) {
158+
if (!in_array($property, $keys)) {
159+
$array[$property] = $value;
160+
}
161+
}
162+
return $this->parseArray($array);
163+
}
164+
165+
public static function arrayOf(array $items): array
166+
{
167+
return array_map(function ($item) {
168+
return $item instanceof static ? $item : new static($item);
169+
}, $items);
170+
}
76171
}

camel/BaseDTOCollection.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44

55
use Illuminate\Contracts\Support\Arrayable;
66
use Illuminate\Support\Collection;
7-
use Spatie\DataTransferObject\DataTransferObjectCollection;
87

98
/**
10-
* @template T of \Spatie\DataTransferObject\DataTransferObject
9+
* @template T of \Knuckles\Camel\BaseDTO
1110
*/
1211
class BaseDTOCollection extends Collection
1312
{

camel/Extraction/ExtractedEndpointData.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,15 +149,17 @@ public function endpointId()
149149
*/
150150
public function forSerialisation()
151151
{
152-
$copy = $this->except(
152+
$copyArray = $this->except(
153153
// Get rid of all duplicate data
154154
'cleanQueryParameters', 'cleanUrlParameters', 'fileParameters', 'cleanBodyParameters',
155155
// and objects used only in extraction
156156
'route', 'controller', 'method', 'auth',
157157
);
158158
// Remove these, since they're on the parent group object
159-
$copy->metadata = $copy->metadata->except('groupName', 'groupDescription');
159+
if (isset($copyArray['metadata']) && $copyArray['metadata'] instanceof Metadata) {
160+
$copyArray['metadata'] = $copyArray['metadata']->except('groupName', 'groupDescription');
161+
}
160162

161-
return $copy;
163+
return $copyArray;
162164
}
163165
}

camel/Output/Parameter.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ class Parameter extends \Knuckles\Camel\Extraction\Parameter
99

1010
public function toArray(): array
1111
{
12-
if (empty($this->exceptKeys)) {
13-
return $this->except('__fields')->toArray();
14-
}
15-
16-
return parent::toArray();
12+
return $this->except('__fields');
1713
}
1814
}

composer.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
"ramsey/uuid": "^4.2.2",
2929
"shalvah/clara": "^3.1.0",
3030
"shalvah/upgrader": ">=0.6.0",
31-
"spatie/data-transfer-object": "^2.6|^3.0",
3231
"symfony/var-exporter": "^6.0|^7.0",
3332
"symfony/yaml": "^6.0|^7.0"
3433
},

0 commit comments

Comments
 (0)