DeferredCallbackCollection.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. <?php
  2. namespace Illuminate\Support\Defer;
  3. use ArrayAccess;
  4. use Closure;
  5. use Countable;
  6. use Illuminate\Support\Collection;
  7. class DeferredCallbackCollection implements ArrayAccess, Countable
  8. {
  9. /**
  10. * All of the deferred callbacks.
  11. *
  12. * @var array
  13. */
  14. protected array $callbacks = [];
  15. /**
  16. * Get the first callback in the collection.
  17. *
  18. * @return callable
  19. */
  20. public function first()
  21. {
  22. return array_values($this->callbacks)[0];
  23. }
  24. /**
  25. * Invoke the deferred callbacks.
  26. *
  27. * @return void
  28. */
  29. public function invoke(): void
  30. {
  31. $this->invokeWhen(fn () => true);
  32. }
  33. /**
  34. * Invoke the deferred callbacks if the given truth test evaluates to true.
  35. *
  36. * @param \Closure|null $when
  37. * @return void
  38. */
  39. public function invokeWhen(?Closure $when = null): void
  40. {
  41. $when ??= fn () => true;
  42. $this->forgetDuplicates();
  43. foreach ($this->callbacks as $index => $callback) {
  44. if ($when($callback)) {
  45. rescue($callback);
  46. }
  47. unset($this->callbacks[$index]);
  48. }
  49. }
  50. /**
  51. * Remove any deferred callbacks with the given name.
  52. *
  53. * @param string $name
  54. * @return void
  55. */
  56. public function forget(string $name): void
  57. {
  58. $this->callbacks = (new Collection($this->callbacks))
  59. ->reject(fn ($callback) => $callback->name === $name)
  60. ->values()
  61. ->all();
  62. }
  63. /**
  64. * Remove any duplicate callbacks.
  65. *
  66. * @return $this
  67. */
  68. protected function forgetDuplicates(): static
  69. {
  70. $this->callbacks = (new Collection($this->callbacks))
  71. ->reverse()
  72. ->unique(fn ($c) => $c->name)
  73. ->reverse()
  74. ->values()
  75. ->all();
  76. return $this;
  77. }
  78. /**
  79. * Determine if the collection has a callback with the given key.
  80. *
  81. * @param mixed $offset
  82. * @return bool
  83. */
  84. public function offsetExists(mixed $offset): bool
  85. {
  86. $this->forgetDuplicates();
  87. return isset($this->callbacks[$offset]);
  88. }
  89. /**
  90. * Get the callback with the given key.
  91. *
  92. * @param mixed $offset
  93. * @return mixed
  94. */
  95. public function offsetGet(mixed $offset): mixed
  96. {
  97. $this->forgetDuplicates();
  98. return $this->callbacks[$offset];
  99. }
  100. /**
  101. * Set the callback with the given key.
  102. *
  103. * @param mixed $offset
  104. * @param mixed $value
  105. * @return void
  106. */
  107. public function offsetSet(mixed $offset, mixed $value): void
  108. {
  109. if (is_null($offset)) {
  110. $this->callbacks[] = $value;
  111. } else {
  112. $this->callbacks[$offset] = $value;
  113. }
  114. }
  115. /**
  116. * Remove the callback with the given key from the collection.
  117. *
  118. * @param mixed $offset
  119. * @return void
  120. */
  121. public function offsetUnset(mixed $offset): void
  122. {
  123. $this->forgetDuplicates();
  124. unset($this->callbacks[$offset]);
  125. }
  126. /**
  127. * Determine how many callbacks are in the collection.
  128. *
  129. * @return int
  130. */
  131. public function count(): int
  132. {
  133. $this->forgetDuplicates();
  134. return count($this->callbacks);
  135. }
  136. }