Macroable.php 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <?php
  2. namespace Illuminate\Support\Traits;
  3. use Closure;
  4. use ReflectionClass;
  5. use ReflectionMethod;
  6. use BadMethodCallException;
  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. * @return void
  22. */
  23. public static function macro($name, $macro)
  24. {
  25. static::$macros[$name] = $macro;
  26. }
  27. /**
  28. * Mix another object into the class.
  29. *
  30. * @param object $mixin
  31. * @return void
  32. */
  33. public static function mixin($mixin)
  34. {
  35. $methods = (new ReflectionClass($mixin))->getMethods(
  36. ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
  37. );
  38. foreach ($methods as $method) {
  39. $method->setAccessible(true);
  40. static::macro($method->name, $method->invoke($mixin));
  41. }
  42. }
  43. /**
  44. * Checks if macro is registered.
  45. *
  46. * @param string $name
  47. * @return bool
  48. */
  49. public static function hasMacro($name)
  50. {
  51. return isset(static::$macros[$name]);
  52. }
  53. /**
  54. * Dynamically handle calls to the class.
  55. *
  56. * @param string $method
  57. * @param array $parameters
  58. * @return mixed
  59. *
  60. * @throws \BadMethodCallException
  61. */
  62. public static function __callStatic($method, $parameters)
  63. {
  64. if (! static::hasMacro($method)) {
  65. throw new BadMethodCallException("Method {$method} does not exist.");
  66. }
  67. if (static::$macros[$method] instanceof Closure) {
  68. return call_user_func_array(Closure::bind(static::$macros[$method], null, static::class), $parameters);
  69. }
  70. return call_user_func_array(static::$macros[$method], $parameters);
  71. }
  72. /**
  73. * Dynamically handle calls to the class.
  74. *
  75. * @param string $method
  76. * @param array $parameters
  77. * @return mixed
  78. *
  79. * @throws \BadMethodCallException
  80. */
  81. public function __call($method, $parameters)
  82. {
  83. if (! static::hasMacro($method)) {
  84. throw new BadMethodCallException("Method {$method} does not exist.");
  85. }
  86. $macro = static::$macros[$method];
  87. if ($macro instanceof Closure) {
  88. return call_user_func_array($macro->bindTo($this, static::class), $parameters);
  89. }
  90. return call_user_func_array($macro, $parameters);
  91. }
  92. }