1: | <?php declare(strict_types=1); |
2: | |
3: | namespace Salient\Core\Concern; |
4: | |
5: | use Salient\Contract\Core\Facade\FacadeAwareInterface; |
6: | use Salient\Contract\Core\Facade\FacadeInterface; |
7: | use Salient\Contract\Core\Instantiable; |
8: | use LogicException; |
9: | |
10: | |
11: | |
12: | |
13: | |
14: | |
15: | |
16: | |
17: | |
18: | |
19: | trait FacadeAwareInstanceTrait |
20: | { |
21: | |
22: | protected ?string $Facade = null; |
23: | |
24: | private ?self $InstanceWithoutFacade = null; |
25: | |
26: | private ?self $InstanceWithFacade = null; |
27: | private bool $HasTentativeFacade = false; |
28: | |
29: | |
30: | |
31: | |
32: | public function withFacade(string $facade) |
33: | { |
34: | if ($this->Facade === $facade) { |
35: | return $this; |
36: | } |
37: | |
38: | if ($this->Facade !== null) { |
39: | throw new LogicException(sprintf( |
40: | '%s already has facade %s', |
41: | static::class, |
42: | $this->Facade, |
43: | )); |
44: | } |
45: | |
46: | |
47: | |
48: | if ( |
49: | $this->InstanceWithoutFacade === $this |
50: | && $this->InstanceWithFacade |
51: | && $this->InstanceWithFacade->Facade === $facade |
52: | ) { |
53: | return $this->InstanceWithFacade; |
54: | } |
55: | |
56: | $this->HasTentativeFacade = true; |
57: | |
58: | $instance = clone $this; |
59: | $instance->Facade = $facade; |
60: | $instance->InstanceWithoutFacade = $this; |
61: | $instance->InstanceWithFacade = $instance; |
62: | $instance->HasTentativeFacade = false; |
63: | |
64: | $this->InstanceWithoutFacade = $this; |
65: | $this->InstanceWithFacade = $instance; |
66: | $this->HasTentativeFacade = false; |
67: | |
68: | return $instance; |
69: | } |
70: | |
71: | |
72: | |
73: | |
74: | public function withoutFacade(string $facade, bool $unloading) |
75: | { |
76: | if ($this->Facade !== $facade) { |
77: | throw new LogicException(sprintf( |
78: | '%s does not have facade %s', |
79: | static::class, |
80: | $facade, |
81: | )); |
82: | } |
83: | |
84: | |
85: | |
86: | if ( |
87: | $this->InstanceWithFacade === $this |
88: | && $this->InstanceWithoutFacade |
89: | && !$unloading |
90: | ) { |
91: | return $this->InstanceWithoutFacade; |
92: | } |
93: | |
94: | $this->HasTentativeFacade = true; |
95: | |
96: | $instance = clone $this; |
97: | $instance->Facade = null; |
98: | $instance->HasTentativeFacade = false; |
99: | |
100: | if ($unloading) { |
101: | $instance->InstanceWithoutFacade = null; |
102: | $instance->InstanceWithFacade = null; |
103: | } else { |
104: | $instance->InstanceWithoutFacade = $instance; |
105: | $instance->InstanceWithFacade = $this; |
106: | |
107: | $this->InstanceWithoutFacade = $instance; |
108: | $this->InstanceWithFacade = $this; |
109: | } |
110: | |
111: | $this->HasTentativeFacade = false; |
112: | |
113: | return $instance; |
114: | } |
115: | |
116: | |
117: | |
118: | |
119: | |
120: | |
121: | |
122: | |
123: | protected function updateFacade(): void |
124: | { |
125: | if ( |
126: | $this->Facade !== null |
127: | && !$this->HasTentativeFacade |
128: | && $this->Facade::isLoaded() |
129: | ) { |
130: | $instance = $this->Facade::getInstance(); |
131: | if ( |
132: | !$instance instanceof static |
133: | || $instance->InstanceWithFacade !== $this |
134: | ) { |
135: | $this->Facade::swap($this); |
136: | } |
137: | } |
138: | } |
139: | } |
140: | |