1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Utils;
9:
10: use Nette;
11:
12:
13: 14: 15: 16: 17:
18: class Callback
19: {
20:
21: 22: 23: 24: 25:
26: public static function closure($callable, $m = NULL)
27: {
28: if ($m !== NULL) {
29: $callable = array($callable, $m);
30: } elseif ($callable instanceof \Closure) {
31: return $callable;
32: }
33:
34: self::check($callable, TRUE);
35: $_callable_ = $callable;
36: return function() use ($_callable_) {
37: Callback::check($_callable_);
38: return call_user_func_array($_callable_, func_get_args());
39: };
40: }
41:
42:
43: 44: 45: 46:
47: public static function invoke($callable)
48: {
49: self::check($callable);
50: return call_user_func_array($callable, array_slice(func_get_args(), 1));
51: }
52:
53:
54: 55: 56: 57:
58: public static function invokeArgs($callable, array $args = array())
59: {
60: self::check($callable);
61: return call_user_func_array($callable, $args);
62: }
63:
64:
65: 66: 67:
68: public static function check($callable, $syntax = FALSE)
69: {
70: if (!is_callable($callable, $syntax)) {
71: throw new Nette\InvalidArgumentException($syntax
72: ? 'Given value is not a callable type.'
73: : sprintf("Callback '%s' is not callable.", self::toString($callable))
74: );
75: }
76: return $callable;
77: }
78:
79:
80: 81: 82:
83: public static function toString($callable)
84: {
85: if ($callable instanceof \Closure) {
86: if ($inner = self::unwrap($callable)) {
87: return '{closure ' . self::toString($inner) . '}';
88: }
89: return '{closure}';
90: } elseif (is_string($callable) && $callable[0] === "\0") {
91: return '{lambda}';
92: } else {
93: is_callable($callable, TRUE, $textual);
94: return $textual;
95: }
96: }
97:
98:
99: 100: 101:
102: public static function toReflection($callable)
103: {
104: if ($callable instanceof \Closure && $inner = self::unwrap($callable)) {
105: $callable = $inner;
106: } elseif ($callable instanceof Nette\Callback) {
107: $callable = $callable->getNative();
108: }
109:
110: $class = class_exists('Nette\Reflection\Method') ? 'Nette\Reflection\Method' : 'ReflectionMethod';
111: if (is_string($callable) && strpos($callable, '::')) {
112: return new $class($callable);
113: } elseif (is_array($callable)) {
114: return new $class($callable[0], $callable[1]);
115: } elseif (is_object($callable) && !$callable instanceof \Closure) {
116: return new $class($callable, '__invoke');
117: } else {
118: $class = class_exists('Nette\Reflection\GlobalFunction') ? 'Nette\Reflection\GlobalFunction' : 'ReflectionFunction';
119: return new $class($callable);
120: }
121: }
122:
123:
124: 125: 126:
127: public static function isStatic($callable)
128: {
129: return is_array($callable) ? is_string($callable[0]) : is_string($callable);
130: }
131:
132:
133:
134: 135: 136: 137: 138:
139: public static function unwrap(\Closure $closure)
140: {
141: $rm = new \ReflectionFunction($closure);
142: $vars = $rm->getStaticVariables();
143: return isset($vars['_callable_']) ? $vars['_callable_'] : NULL;
144: }
145:
146: }
147: