Macroable.php 2.8 KB

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