Macroable.php 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. * @throws \ReflectionException
  33. */
  34. public static function mixin($mixin)
  35. {
  36. $methods = (new ReflectionClass($mixin))->getMethods(
  37. ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
  38. );
  39. foreach ($methods as $method) {
  40. $method->setAccessible(true);
  41. static::macro($method->name, $method->invoke($mixin));
  42. }
  43. }
  44. /**
  45. * Checks if macro is registered.
  46. *
  47. * @param string $name
  48. * @return bool
  49. */
  50. public static function hasMacro($name)
  51. {
  52. return isset(static::$macros[$name]);
  53. }
  54. /**
  55. * Dynamically handle calls to the class.
  56. *
  57. * @param string $method
  58. * @param array $parameters
  59. * @return mixed
  60. *
  61. * @throws \BadMethodCallException
  62. */
  63. public static function __callStatic($method, $parameters)
  64. {
  65. if (! static::hasMacro($method)) {
  66. throw new BadMethodCallException(sprintf(
  67. 'Method %s::%s does not exist.', static::class, $method
  68. ));
  69. }
  70. if (static::$macros[$method] instanceof Closure) {
  71. return call_user_func_array(Closure::bind(static::$macros[$method], null, static::class), $parameters);
  72. }
  73. return call_user_func_array(static::$macros[$method], $parameters);
  74. }
  75. /**
  76. * Dynamically handle calls to the class.
  77. *
  78. * @param string $method
  79. * @param array $parameters
  80. * @return mixed
  81. *
  82. * @throws \BadMethodCallException
  83. */
  84. public function __call($method, $parameters)
  85. {
  86. if (! static::hasMacro($method)) {
  87. throw new BadMethodCallException(sprintf(
  88. 'Method %s::%s does not exist.', static::class, $method
  89. ));
  90. }
  91. $macro = static::$macros[$method];
  92. if ($macro instanceof Closure) {
  93. return call_user_func_array($macro->bindTo($this, static::class), $parameters);
  94. }
  95. return call_user_func_array($macro, $parameters);
  96. }
  97. }