PluginProbe
Packeta / 2.1
Packeta v2.1
2.3.2 2.3.1 trunk 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.3.0 1.3.1 1.3.2 1.4 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 All 56 releases
packeta / deps / nette / utils / src / Utils / Callback.php

Callback.php in Packeta 2.1, at deps/nette/utils/src/Utils/Callback.php

151 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * This file is part of the Nette Framework (https://nette.org)
5 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6 */
7 declare (strict_types=1);
8 namespace Packetery\Nette\Utils;
9
10 use Packetery\Nette;
11 use function is_array, is_object, is_string;
12 /**
13 * PHP callable tools.
14 */
15 final class Callback
16 {
17 use \Packetery\Nette\StaticClass;
18 /**
19 * @param string|object|callable $callable class, object, callable
20 * @deprecated use Closure::fromCallable()
21 */
22 public static function closure($callable, ?string $method = null) : \Closure
23 {
24 \trigger_error(__METHOD__ . '() is deprecated, use Closure::fromCallable().', \E_USER_DEPRECATED);
25 try {
26 return \Closure::fromCallable($method === null ? $callable : [$callable, $method]);
27 } catch (\TypeError $e) {
28 throw new \Packetery\Nette\InvalidArgumentException($e->getMessage());
29 }
30 }
31 /**
32 * Invokes callback.
33 * @return mixed
34 * @deprecated
35 */
36 public static function invoke($callable, ...$args)
37 {
38 \trigger_error(__METHOD__ . '() is deprecated, use native invoking.', \E_USER_DEPRECATED);
39 self::check($callable);
40 return $callable(...$args);
41 }
42 /**
43 * Invokes callback with an array of parameters.
44 * @return mixed
45 * @deprecated
46 */
47 public static function invokeArgs($callable, array $args = [])
48 {
49 \trigger_error(__METHOD__ . '() is deprecated, use native invoking.', \E_USER_DEPRECATED);
50 self::check($callable);
51 return $callable(...$args);
52 }
53 /**
54 * Invokes internal PHP function with own error handler.
55 * @return mixed
56 */
57 public static function invokeSafe(string $function, array $args, callable $onError)
58 {
59 $prev = \set_error_handler(function ($severity, $message, $file) use($onError, &$prev, $function) : ?bool {
60 if ($file === __FILE__) {
61 $msg = \ini_get('html_errors') ? Html::htmlToText($message) : $message;
62 $msg = \preg_replace("#^{$function}\\(.*?\\): #", '', $msg);
63 if ($onError($msg, $severity) !== \false) {
64 return null;
65 }
66 }
67 return $prev ? $prev(...\func_get_args()) : \false;
68 });
69 try {
70 return $function(...$args);
71 } finally {
72 \restore_error_handler();
73 }
74 }
75 /**
76 * Checks that $callable is valid PHP callback. Otherwise throws exception. If the $syntax is set to true, only verifies
77 * that $callable has a valid structure to be used as a callback, but does not verify if the class or method actually exists.
78 * @param mixed $callable
79 * @return callable
80 * @throws \Packetery\Nette\InvalidArgumentException
81 */
82 public static function check($callable, bool $syntax = \false)
83 {
84 if (!\is_callable($callable, $syntax)) {
85 throw new \Packetery\Nette\InvalidArgumentException($syntax ? 'Given value is not a callable type.' : \sprintf("Callback '%s' is not callable.", self::toString($callable)));
86 }
87 return $callable;
88 }
89 /**
90 * Converts PHP callback to textual form. Class or method may not exists.
91 * @param mixed $callable
92 */
93 public static function toString($callable) : string
94 {
95 if ($callable instanceof \Closure) {
96 $inner = self::unwrap($callable);
97 return '{closure' . ($inner instanceof \Closure ? '}' : ' ' . self::toString($inner) . '}');
98 } elseif (is_string($callable) && $callable[0] === "\x00") {
99 return '{lambda}';
100 } else {
101 \is_callable(is_object($callable) ? [$callable, '__invoke'] : $callable, \true, $textual);
102 return $textual;
103 }
104 }
105 /**
106 * Returns reflection for method or function used in PHP callback.
107 * @param callable $callable type check is escalated to ReflectionException
108 * @return \ReflectionMethod|\ReflectionFunction
109 * @throws \ReflectionException if callback is not valid
110 */
111 public static function toReflection($callable) : \ReflectionFunctionAbstract
112 {
113 if ($callable instanceof \Closure) {
114 $callable = self::unwrap($callable);
115 }
116 if (is_string($callable) && \strpos($callable, '::')) {
117 return new \ReflectionMethod($callable);
118 } elseif (is_array($callable)) {
119 return new \ReflectionMethod($callable[0], $callable[1]);
120 } elseif (is_object($callable) && !$callable instanceof \Closure) {
121 return new \ReflectionMethod($callable, '__invoke');
122 } else {
123 return new \ReflectionFunction($callable);
124 }
125 }
126 /**
127 * Checks whether PHP callback is function or static method.
128 */
129 public static function isStatic(callable $callable) : bool
130 {
131 return is_array($callable) ? is_string($callable[0]) : is_string($callable);
132 }
133 /**
134 * Unwraps closure created by Closure::fromCallable().
135 * @return callable|array
136 */
137 public static function unwrap(\Closure $closure)
138 {
139 $r = new \ReflectionFunction($closure);
140 if (\substr($r->name, -1) === '}') {
141 return $closure;
142 } elseif ($obj = $r->getClosureThis()) {
143 return [$obj, $r->name];
144 } elseif ($class = $r->getClosureScopeClass()) {
145 return [$class->name, $r->name];
146 } else {
147 return $r->name;
148 }
149 }
150 }
151