Skip to content

Commit 7ae0fc9

Browse files
[12.x] Adds AsInstance::of() cast
1 parent fba3b98 commit 7ae0fc9

File tree

4 files changed

+398
-4
lines changed

4 files changed

+398
-4
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
namespace Illuminate\Database\Eloquent\Casts;
4+
5+
use Illuminate\Contracts\Database\Eloquent\Castable;
6+
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
7+
use Illuminate\Contracts\Support\Arrayable;
8+
use Illuminate\Contracts\Support\Jsonable;
9+
use Illuminate\Support\Facades\Crypt;
10+
use InvalidArgumentException;
11+
use ValueError;
12+
13+
class AsEncryptedInstance implements Castable
14+
{
15+
/**
16+
* Get the caster class to use when casting from / to this cast target.
17+
*
18+
* @param array $arguments
19+
* @return \Illuminate\Contracts\Database\Eloquent\CastsAttributes<\Illuminate\Support\Collection<array-key, mixed>, iterable>
20+
*/
21+
public static function castUsing(array $arguments)
22+
{
23+
return new class($arguments) implements CastsAttributes
24+
{
25+
protected string $class;
26+
27+
public function __construct(array $arguments)
28+
{
29+
$this->class = $arguments[0]
30+
?? throw new InvalidArgumentException('A class name must be provided to cast as an instance.');
31+
}
32+
33+
public function get($model, $key, $value, $attributes)
34+
{
35+
if (! isset($attributes[$key])) {
36+
return;
37+
}
38+
39+
$data = Json::decode(Crypt::decryptString($attributes[$key]));
40+
41+
if (! is_array($data)) {
42+
return null;
43+
}
44+
45+
if (method_exists($this->class, 'fromArray')) {
46+
return $this->class::fromArray($data);
47+
}
48+
49+
return new $this->class($data);
50+
}
51+
52+
public function set($model, $key, $value, $attributes)
53+
{
54+
if (! is_null($value)) {
55+
return [
56+
$key => Crypt::encryptString(
57+
match(true) {
58+
$value instanceof Jsonable => $value->toJson(),
59+
$value instanceof Arrayable => Json::encode($value->toArray()),
60+
default => throw new ValueError(sprintf(
61+
'The %s class should implement Jsonable or Arrayable contract.', $this->class
62+
))
63+
}
64+
)
65+
];
66+
}
67+
68+
return null;
69+
}
70+
};
71+
}
72+
73+
/**
74+
* Specify the class to make an instance from.
75+
*
76+
* @param class-string $class
77+
* @return string
78+
*/
79+
public static function of($class)
80+
{
81+
return static::class . ':' . $class;
82+
}
83+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
namespace Illuminate\Database\Eloquent\Casts;
4+
5+
use Illuminate\Contracts\Database\Eloquent\Castable;
6+
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
7+
use Illuminate\Contracts\Support\Arrayable;
8+
use Illuminate\Contracts\Support\Jsonable;
9+
use InvalidArgumentException;
10+
use ValueError;
11+
12+
class AsInstance implements Castable
13+
{
14+
/**
15+
* Get the caster class to use when casting from / to this cast target.
16+
*
17+
* @param array $arguments
18+
* @return \Illuminate\Contracts\Database\Eloquent\CastsAttributes<\Illuminate\Support\Collection<array-key, mixed>, iterable>
19+
*/
20+
public static function castUsing(array $arguments)
21+
{
22+
return new class($arguments) implements CastsAttributes
23+
{
24+
protected string $class;
25+
26+
public function __construct(array $arguments)
27+
{
28+
$this->class = $arguments[0]
29+
?? throw new InvalidArgumentException('A class name must be provided to cast as an instance.');
30+
}
31+
32+
public function get($model, $key, $value, $attributes)
33+
{
34+
if (! isset($attributes[$key])) {
35+
return;
36+
}
37+
38+
$data = Json::decode($attributes[$key]);
39+
40+
if (! is_array($data)) {
41+
return null;
42+
}
43+
44+
if (method_exists($this->class, 'fromArray')) {
45+
return $this->class::fromArray($data);
46+
}
47+
48+
return new $this->class($data);
49+
}
50+
51+
public function set($model, $key, $value, $attributes)
52+
{
53+
if (! isset($attributes[$key])) {
54+
return;
55+
}
56+
57+
return [
58+
$key => match(true) {
59+
$value instanceof Jsonable => $value->toJson(),
60+
$value instanceof Arrayable => Json::encode($value->toArray()),
61+
default => throw new ValueError(sprintf(
62+
'The %s class should implement Jsonable or Arrayable contract.', $this->class)
63+
)
64+
}
65+
];
66+
}
67+
};
68+
}
69+
70+
/**
71+
* Specify the class to make an instance from.
72+
*
73+
* @param class-string $class
74+
* @return string
75+
*/
76+
public static function of($class)
77+
{
78+
return static::class . ':' . $class;
79+
}
80+
}

0 commit comments

Comments
 (0)