Macroable.php 2.7 KB

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