1--TEST-- 2Ensure type hints are enforced for functions invoked as callbacks. 3--FILE-- 4<?php 5 set_error_handler('myErrorHandler', E_RECOVERABLE_ERROR); 6 function myErrorHandler($errno, $errstr, $errfile, $errline) { 7 echo "$errno: $errstr - $errfile($errline)\n"; 8 return true; 9 } 10 11 echo "---> Type hints with callback function:\n"; 12 class A { } 13 function f1(A $a) { 14 echo "in f1;\n"; 15 } 16 function f2(A $a = null) { 17 echo "in f2;\n"; 18 } 19 try { 20 call_user_func('f1', 1); 21 } catch (Error $ex) { 22 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 23 } 24 try { 25 call_user_func('f1', new A); 26 } catch (Error $ex) { 27 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 28 } 29 try { 30 call_user_func('f2', 1); 31 } catch (Error $ex) { 32 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 33 } 34 try { 35 call_user_func('f2'); 36 } catch (Error $ex) { 37 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 38 } 39 try { 40 call_user_func('f2', new A); 41 } catch (Error $ex) { 42 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 43 } 44 try { 45 call_user_func('f2', null); 46 } catch (Error $ex) { 47 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 48 } 49 50 echo "\n\n---> Type hints with callback static method:\n"; 51 class C { 52 static function f1(A $a) { 53 if (isset($this)) { 54 echo "in C::f1 (instance);\n"; 55 } else { 56 echo "in C::f1 (static);\n"; 57 } 58 } 59 static function f2(A $a = null) { 60 if (isset($this)) { 61 echo "in C::f2 (instance);\n"; 62 } else { 63 echo "in C::f2 (static);\n"; 64 } 65 } 66 } 67 68 try { 69 call_user_func(array('C', 'f1'), 1); 70 } catch (Error $ex) { 71 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 72 } 73 try { 74 call_user_func(array('C', 'f1'), new A); 75 } catch (Error $ex) { 76 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 77 } 78 try { 79 call_user_func(array('C', 'f2'), 1); 80 } catch (Error $ex) { 81 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 82 } 83 try { 84 call_user_func(array('C', 'f2')); 85 } catch (Error $ex) { 86 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 87 } 88 try { 89 call_user_func(array('C', 'f2'), new A); 90 } catch (Error $ex) { 91 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 92 } 93 try { 94 call_user_func(array('C', 'f2'), null); 95 } catch (Error $ex) { 96 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 97 } 98 99 echo "\n\n---> Type hints with callback instance method:\n"; 100 class D { 101 function f1(A $a) { 102 if (isset($this)) { 103 echo "in C::f1 (instance);\n"; 104 } else { 105 echo "in C::f1 (static);\n"; 106 } 107 } 108 function f2(A $a = null) { 109 if (isset($this)) { 110 echo "in C::f2 (instance);\n"; 111 } else { 112 echo "in C::f2 (static);\n"; 113 } 114 } 115 } 116 $d = new D; 117 118 try { 119 call_user_func(array($d, 'f1'), 1); 120 } catch (Error $ex) { 121 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 122 } 123 try { 124 call_user_func(array($d, 'f1'), new A); 125 } catch (Error $ex) { 126 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 127 } 128 try { 129 call_user_func(array($d, 'f2'), 1); 130 } catch (Error $ex) { 131 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 132 } 133 try { 134 call_user_func(array($d, 'f2')); 135 } catch (Error $ex) { 136 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 137 } 138 try { 139 call_user_func(array($d, 'f2'), new A); 140 } catch (Error $ex) { 141 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 142 } 143 try { 144 call_user_func(array($d, 'f2'), null); 145 } catch (Error $ex) { 146 echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; 147 } 148 149?> 150--EXPECTF-- 151---> Type hints with callback function: 1520: Argument 1 passed to f1() must be an instance of A, integer given%s(%d) 153 154in f1; 1550: Argument 1 passed to f2() must be an instance of A or null, integer given%s(%d) 156 157in f2; 158in f2; 159in f2; 160 161 162---> Type hints with callback static method: 1630: Argument 1 passed to C::f1() must be an instance of A, integer given%s(%d) 164 165in C::f1 (static); 1660: Argument 1 passed to C::f2() must be an instance of A or null, integer given%s(%d) 167 168in C::f2 (static); 169in C::f2 (static); 170in C::f2 (static); 171 172 173---> Type hints with callback instance method: 1740: Argument 1 passed to D::f1() must be an instance of A, integer given%s(%d) 175 176in C::f1 (instance); 1770: Argument 1 passed to D::f2() must be an instance of A or null, integer given%s(%d) 178 179in C::f2 (instance); 180in C::f2 (instance); 181in C::f2 (instance); 182