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: 69:
70: public static function invokeSafe($function, array $args, $onError)
71: {
72: $prev = set_error_handler(function ($severity, $message, $file) use ($onError, & $prev) {
73: if ($file === __FILE__ && $onError($message, $severity) !== FALSE) {
74: return;
75: } elseif ($prev) {
76: return call_user_func_array($prev, func_get_args());
77: }
78: return FALSE;
79: });
80:
81: try {
82: $res = call_user_func_array($function, $args);
83: restore_error_handler();
84: return $res;
85:
86: } catch (\Exception $e) {
87: restore_error_handler();
88: throw $e;
89: }
90: }
91:
92:
93: 94: 95:
96: public static function check($callable, $syntax = FALSE)
97: {
98: if (!is_callable($callable, $syntax)) {
99: throw new Nette\InvalidArgumentException($syntax
100: ? 'Given value is not a callable type.'
101: : sprintf("Callback '%s' is not callable.", self::toString($callable))
102: );
103: }
104: return $callable;
105: }
106:
107:
108: 109: 110:
111: public static function toString($callable)
112: {
113: if ($callable instanceof \Closure) {
114: if ($inner = self::unwrap($callable)) {
115: return '{closure ' . self::toString($inner) . '}';
116: }
117: return '{closure}';
118: } elseif (is_string($callable) && $callable[0] === "\0") {
119: return '{lambda}';
120: } else {
121: is_callable($callable, TRUE, $textual);
122: return $textual;
123: }
124: }
125:
126:
127: 128: 129:
130: public static function toReflection($callable)
131: {
132: if ($callable instanceof \Closure && $inner = self::unwrap($callable)) {
133: $callable = $inner;
134: } elseif ($callable instanceof Nette\Callback) {
135: $callable = $callable->getNative();
136: }
137:
138: if (is_string($callable) && strpos($callable, '::')) {
139: return new Nette\Reflection\Method($callable);
140: } elseif (is_array($callable)) {
141: return new Nette\Reflection\Method($callable[0], $callable[1]);
142: } elseif (is_object($callable) && !$callable instanceof \Closure) {
143: return new Nette\Reflection\Method($callable, '__invoke');
144: } else {
145: return new Nette\Reflection\GlobalFunction($callable);
146: }
147: }
148:
149:
150: 151: 152:
153: public static function isStatic($callable)
154: {
155: return is_array($callable) ? is_string($callable[0]) : is_string($callable);
156: }
157:
158:
159: 160: 161: 162: 163:
164: public static function unwrap(\Closure $closure)
165: {
166: $rm = new \ReflectionFunction($closure);
167: $vars = $rm->getStaticVariables();
168: return isset($vars['_callable_']) ? $vars['_callable_'] : NULL;
169: }
170:
171: }
172: