-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathImmutable.php
More file actions
81 lines (68 loc) · 2.03 KB
/
Immutable.php
File metadata and controls
81 lines (68 loc) · 2.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<?php
/**
* This file is part of phpfn package.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Fun\Immutable;
use Fun\Immutable\Exception\ContextException;
use Fun\Immutable\Exception\IntegrityException;
final class Immutable
{
/**
* @var string
*/
private const ERROR_LOST_CONTEXT =
'Can not create an immutable object, because \Closure ' .
'argument does not contain the context. Make sure the \Closure is ' .
'not static and/or used inside an object';
/**
* @deprecated Please use {@see Immutable::make()} function instead.
*
* @param \Closure $expr
* @param object|null $context
* @return object
*/
public static function execute(\Closure $expr, object $context = null): object
{
return self::make($expr, $context);
}
/**
* @template T of object
* @param \Closure $expr
* @param T|null $context
* @return T
*/
public static function make(\Closure $expr, object $context = null): object
{
$context = self::resolveContext($expr, $context);
try {
$self = clone $context;
} catch (\Throwable $e) {
throw new IntegrityException($e->getMessage(), 0x01);
}
$expr->call($self);
return $self;
}
/**
* @template T of object
* @param \Closure $callable
* @param T|null $context
* @return T
*/
private static function resolveContext(\Closure $callable, object $context = null): object
{
try {
/** @var object|null $context */
$context = $context ?? (new \ReflectionFunction($callable))->getClosureThis();
} catch (\ReflectionException $e) {
throw new ContextException($e->getMessage(), 0x01);
}
if ($context === null) {
throw new ContextException(self::ERROR_LOST_CONTEXT, 0x02);
}
return $context;
}
}