-
Notifications
You must be signed in to change notification settings - Fork 0
/
Mixin.php
138 lines (125 loc) · 3.48 KB
/
Mixin.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<?php
/**
* @link https://github.com/ryanve/traits
*/
namespace traits;
use \Closure;
trait Mixin {
function __call($name, $params) {
return static::resolve($name, $params, $this);
}
static function __callStatic($name, $params) {
return static::resolve($name, $params);
}
/**
* @param string|int $name
* @param array $params
* @param object $scope
* @return mixed
*/
static function resolve($name, array $params = null, $scope = null) {
if ($fn = static::mixin((string) $name))
return static::apply($fn, $scope, $params);
if ('_e' === substr($name, -2))
echo static::apply(static::method(substr($name, 0, -2), $scope), null, $params);
else trigger_error(get_called_class() . " method '$name' is not callable.");
}
/**
* @param array|object|string|int $name
* @param callable|string $fn
* @param int|bool $chain
* @return mixed
*/
static function mixin($name, $fn = 0, $chain = 0) {
static $mixins;
$mixins = $mixins ?: [[], []];
$name and $name = static::result($name);
if (is_scalar($name)) {
$chain = (int) $chain;
$fn and $mixins[$chain][$name] = $fn;
return empty($mixins[$chain][$name])
? null : $mixins[$chain][$name];
}
$chain = (int) $fn;
if ($name)
foreach ($name as $k => $v)
$v and $mixins[$chain][$k] = $v;
return $copy = $mixins[$chain];
}
/**
* @param mixed $fn
* @return mixed
*/
static function result($fn) {
return $fn instanceof Closure ? call_user_func_array($fn, array_slice(func_get_args(), 1)) : $fn;
}
/**
* @param callable $fn
* @param object $scope
* @return mixed
*/
static function call(callable $fn, $scope = null) {
return static::apply($fn, $scope, array_slice(func_get_args(), 2));
}
/**
* @param callable $fn
* @param object $scope
* @param array $params
* @return mixed
*/
static function apply(callable $fn, $scope = null, array $params = null) {
null !== $scope && $fn instanceof Closure and $fn = Closure::bind($fn, $scope, get_class($scope));
return call_user_func_array($fn, $params ?: []);
}
/**
* @deprecated
* @param callable $fn
* @return callable
*/
static function curry($fn) {
$curries = array_slice(func_get_args(), 1);
return function() use ($fn, $curries) {
return call_user_func_array($fn, array_merge($curries, func_get_args()));
};
}
/**
* @deprecated
* @param callable $fn
* @return callable
*/
static function partial($fn) {
$curries = array_slice(func_get_args(), 1);
return function() use ($fn, $curries) {
$params = func_get_args();
foreach ($curries as $i => $v)
$params[$i] = null === $v && array_key_exists($i, $params) ? $params[$i] : $v;
return call_user_func_array($fn, $params);
};
}
/**
* @param string $name
* @param string|object $scope
* @return callable
*/
static function method($name, $scope = null) {
return [null === $scope ? get_called_class() : $scope, $name];
}
/**
* @param string|object $object
* @return array
*/
static function methods($object = null) {
$result = [];
null === $object and $object = get_called_class();
foreach (get_class_methods($object) as $m)
$result[$m] = [$object, $m];
return $result;
}
/**
* @param object $object
* @return array
*/
function vars($object = null) {
return get_object_vars(null === $object ? $this : $object);
}
}