Macroable.php 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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\Macroable;
  12. use BadMethodCallException;
  13. use Closure;
  14. use ReflectionClass;
  15. use ReflectionMethod;
  16. /**
  17. * This file come from illuminate/macroable,
  18. * thanks Laravel Team provide such a useful class.
  19. */
  20. trait Macroable
  21. {
  22. /**
  23. * The registered string macros.
  24. *
  25. * @var array
  26. */
  27. protected static $macros = [];
  28. /**
  29. * Dynamically handle calls to the class.
  30. *
  31. * @param string $method
  32. * @param array $parameters
  33. * @throws \BadMethodCallException
  34. * @return mixed
  35. */
  36. public static function __callStatic($method, $parameters)
  37. {
  38. if (! static::hasMacro($method)) {
  39. throw new BadMethodCallException(sprintf(
  40. 'Method %s::%s does not exist.',
  41. static::class,
  42. $method
  43. ));
  44. }
  45. $macro = static::$macros[$method];
  46. if ($macro instanceof Closure) {
  47. $macro = $macro->bindTo(null, static::class);
  48. }
  49. return $macro(...$parameters);
  50. }
  51. /**
  52. * Dynamically handle calls to the class.
  53. *
  54. * @param string $method
  55. * @param array $parameters
  56. * @throws \BadMethodCallException
  57. * @return mixed
  58. */
  59. public function __call($method, $parameters)
  60. {
  61. if (! static::hasMacro($method)) {
  62. throw new BadMethodCallException(sprintf(
  63. 'Method %s::%s does not exist.',
  64. static::class,
  65. $method
  66. ));
  67. }
  68. $macro = static::$macros[$method];
  69. if ($macro instanceof Closure) {
  70. $macro = $macro->bindTo($this, static::class);
  71. }
  72. return $macro(...$parameters);
  73. }
  74. /**
  75. * Register a custom macro.
  76. *
  77. * @param string $name
  78. * @param callable|object $macro
  79. */
  80. public static function macro($name, $macro)
  81. {
  82. static::$macros[$name] = $macro;
  83. }
  84. /**
  85. * Mix another object into the class.
  86. *
  87. * @param object $mixin
  88. * @param bool $replace
  89. *
  90. * @throws \ReflectionException
  91. */
  92. public static function mixin($mixin, $replace = true)
  93. {
  94. $methods = (new ReflectionClass($mixin))->getMethods(
  95. ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
  96. );
  97. foreach ($methods as $method) {
  98. if ($replace || ! static::hasMacro($method->name)) {
  99. $method->setAccessible(true);
  100. static::macro($method->name, $method->invoke($mixin));
  101. }
  102. }
  103. }
  104. /**
  105. * Checks if macro is registered.
  106. *
  107. * @param string $name
  108. * @return bool
  109. */
  110. public static function hasMacro($name)
  111. {
  112. return isset(static::$macros[$name]);
  113. }
  114. }