56 $this->callable = $callable;
74 return static::represent($this->callable);
90 public static function wrap($callable)
92 $parts = explode(
'::', static::represent($callable));
93 if (count($parts) == 1) {
95 $reflector = new \ReflectionFunction($callable);
97 if (!is_array($callable)) {
99 $callable = array($callable, $parts[1]);
101 $reflector = new \ReflectionMethod($callable[0], $callable[1]);
107 foreach ($reflector->getParameters() as $argReflect) {
109 if ($argReflect->isPassedByReference()) {
112 $arg .=
'$a' . count($args);
113 if ($argReflect->isOptional()) {
114 $arg .=
'=' . var_export($argReflect->getDefaultValue(),
true);
121 $args = implode(
',', $args);
122 $class =
'Wrapped_' . sha1($args);
123 if (!class_exists(
"\\Erebot\\CallableWrapper\\$class",
false)) {
125 namespace Erebot\\CallableWrapper { 126 class $class extends \\Erebot\\CallableWrapper 128 public function __invoke($args) 130 // HACK: we use debug_backtrace() to get (and pass along) 131 // references for call_user_func_array(). 133 // Starting with PHP 5.4.0, it is possible to limit 134 // the number of stack frames returned. 135 if (version_compare(PHP_VERSION, '5.4', '>=')) 136 \$bt = debug_backtrace(0, 1); 137 // Starting with PHP 5.3.6, the first argument 138 // to debug_backtrace() is a bitmask of options. 139 else if (version_compare(PHP_VERSION, '5.3.6', '>=')) 140 \$bt = debug_backtrace(0); 142 \$bt = debug_backtrace(FALSE); 144 if (isset(\$bt[0]['args'])) 145 \$args =& \$bt[0]['args']; 148 return call_user_func_array(\$this->callable, \$args); 155 $class =
"\\Erebot\\CallableWrapper\\$class";
156 return new $class($callable);
182 static $initialized =
false;
183 static $structures = array();
185 if (defined(
'T_CALLABLE'))
189 spl_autoload_register(
191 $parts = array_map(
'strrev', explode(
'\\', strrev($class), 2));
192 $short = array_shift($parts);
193 $ns = (string) array_shift($parts);
195 if ($short ===
'callable') {
197 if (class_alias(
'\\Erebot\\CallableInterface', $class,
true) !==
true) {
198 throw new \RuntimeException(
'Could not load wrapper');
205 class_exists(
"$ns\\callable");
214 $funcs = get_defined_functions();
217 get_declared_classes(),
218 get_declared_interfaces()
221 if ($new != $structures) {
223 foreach (array_diff($new, $structures) as $structure) {
224 $parts = explode(
'\\', strrev($structure), 2);
226 $newNS[] = (string) array_shift($parts);
229 $newNS = array_unique($newNS);
230 foreach ($newNS as $ns) {
231 class_exists(strrev($ns) .
'\\callable');
258 if (!is_callable($callable,
false, $representation)) {
259 throw new \InvalidArgumentException(
'Not a valid callable');
264 if (is_string($callable) && $representation ==
"") {
265 $representation = $callable;
267 return $representation;
Interface for something that can be called.
$callable
Inner callable object, as used by PHP.
Class used to represent anything that is callable.
static represent($callable)
$representation
Human representation of the inner callable.