1: <?php declare(strict_types=1);
2:
3: namespace Salient\Core\Concern;
4:
5: use Salient\Contract\Core\FacadeAwareInterface;
6: use Salient\Contract\Core\FacadeInterface;
7: use Salient\Utility\Get;
8: use LogicException;
9:
10: /**
11: * Implements FacadeAwareInterface by maintaining a list of facades the instance
12: * is being used by
13: *
14: * @see FacadeAwareInterface
15: *
16: * @api
17: *
18: * @template TFacade of FacadeInterface
19: */
20: trait UnloadsFacades
21: {
22: /**
23: * Normalised FQCN => given FQCN
24: *
25: * @var array<class-string<TFacade>,class-string<TFacade>>
26: */
27: private $Facades = [];
28:
29: /**
30: * @param class-string<TFacade> $facade
31: * @return static
32: */
33: final public function withFacade(string $facade)
34: {
35: $this->Facades[Get::fqcn($facade)] = $facade;
36: return $this;
37: }
38:
39: /**
40: * @param class-string<TFacade> $facade
41: * @return static
42: */
43: final public function withoutFacade(string $facade, bool $unloading)
44: {
45: if ($unloading) {
46: unset($this->Facades[Get::fqcn($facade)]);
47: }
48: return $this;
49: }
50:
51: /**
52: * Unload any facades where the object is the underlying instance
53: */
54: final protected function unloadFacades(): void
55: {
56: if (!$this->Facades) {
57: return;
58: }
59:
60: foreach ($this->Facades as $fqcn => $facade) {
61: if (!$facade::isLoaded() || $facade::getInstance() !== $this) {
62: // @codeCoverageIgnoreStart
63: unset($this->Facades[$fqcn]);
64: continue;
65: // @codeCoverageIgnoreEnd
66: }
67:
68: $facade::unload();
69: }
70:
71: if (!$this->Facades) {
72: return;
73: }
74:
75: // @codeCoverageIgnoreStart
76: throw new LogicException(sprintf(
77: 'Underlying %s not unloaded: %s',
78: static::class,
79: implode(' ', $this->Facades),
80: ));
81: // @codeCoverageIgnoreEnd
82: }
83: }
84: