Context.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of Hyperf.
  5. *
  6. * @link https://www.hyperf.io
  7. * @document https://hyperf.wiki
  8. * @contact group@hyperf.io
  9. * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
  10. */
  11. namespace Hyperf\Context;
  12. use Closure;
  13. use Hyperf\Engine\Coroutine;
  14. use function Hyperf\Support\value;
  15. class Context
  16. {
  17. protected static array $nonCoContext = [];
  18. public static function set(string $id, mixed $value, ?int $coroutineId = null): mixed
  19. {
  20. if (Coroutine::id() > 0) {
  21. Coroutine::getContextFor($coroutineId)[$id] = $value;
  22. } else {
  23. static::$nonCoContext[$id] = $value;
  24. }
  25. return $value;
  26. }
  27. public static function get(string $id, mixed $default = null, ?int $coroutineId = null): mixed
  28. {
  29. if (Coroutine::id() > 0) {
  30. return Coroutine::getContextFor($coroutineId)[$id] ?? $default;
  31. }
  32. return static::$nonCoContext[$id] ?? $default;
  33. }
  34. public static function has(string $id, ?int $coroutineId = null): bool
  35. {
  36. if (Coroutine::id() > 0) {
  37. return isset(Coroutine::getContextFor($coroutineId)[$id]);
  38. }
  39. return isset(static::$nonCoContext[$id]);
  40. }
  41. /**
  42. * Release the context when you are not in coroutine environment.
  43. */
  44. public static function destroy(string $id, ?int $coroutineId = null): void
  45. {
  46. if (Coroutine::id() > 0) {
  47. unset(Coroutine::getContextFor($coroutineId)[$id]);
  48. }
  49. unset(static::$nonCoContext[$id]);
  50. }
  51. /**
  52. * Copy the context from a coroutine to current coroutine.
  53. * This method will delete the origin values in current coroutine.
  54. */
  55. public static function copy(int $fromCoroutineId, array $keys = []): void
  56. {
  57. $from = Coroutine::getContextFor($fromCoroutineId);
  58. if ($from === null) {
  59. return;
  60. }
  61. $current = Coroutine::getContextFor();
  62. if ($keys) {
  63. $map = array_intersect_key($from->getArrayCopy(), array_flip($keys));
  64. } else {
  65. $map = $from->getArrayCopy();
  66. }
  67. $current->exchangeArray($map);
  68. }
  69. /**
  70. * Retrieve the value and override it by closure.
  71. */
  72. public static function override(string $id, Closure $closure, ?int $coroutineId = null): mixed
  73. {
  74. $value = null;
  75. if (self::has($id, $coroutineId)) {
  76. $value = self::get($id, null, $coroutineId);
  77. }
  78. $value = $closure($value);
  79. self::set($id, $value, $coroutineId);
  80. return $value;
  81. }
  82. /**
  83. * Retrieve the value and store it if not exists.
  84. */
  85. public static function getOrSet(string $id, mixed $value, ?int $coroutineId = null): mixed
  86. {
  87. if (! self::has($id, $coroutineId)) {
  88. return self::set($id, value($value), $coroutineId);
  89. }
  90. return self::get($id, null, $coroutineId);
  91. }
  92. public static function getContainer(?int $coroutineId = null)
  93. {
  94. if (Coroutine::id() > 0) {
  95. return Coroutine::getContextFor($coroutineId);
  96. }
  97. return static::$nonCoContext;
  98. }
  99. }