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