1--TEST-- 2registerPhpFunctionNS() function - legit cases 3--EXTENSIONS-- 4dom 5--FILE-- 6<?php 7 8class TrampolineClass { 9 public static function __callStatic(string $name, array $arguments): mixed { 10 var_dump($name, $arguments); 11 return strtoupper($arguments[0]); 12 } 13} 14 15class StatefulClass { 16 public array $state = []; 17 18 public function __call(string $name, array $arguments): mixed { 19 $this->state[] = [$name, $arguments[0]]; 20 return $arguments[0]; 21 } 22} 23 24$doc = new DOMDocument(); 25$doc->loadHTML('<a href="https://PHP.net">hello</a>'); 26 27$xpath = new DOMXPath($doc); 28 29$xpath->registerNamespace('foo', 'urn:foo'); 30 31echo "--- Legit cases: global function callable ---\n"; 32 33$xpath->registerPhpFunctionNS('urn:foo', 'strtolower', strtolower(...)); 34var_dump($xpath->query('//a[foo:strtolower(string(@href)) = "https://php.net"]')); 35 36echo "--- Legit cases: string callable ---\n"; 37 38$xpath->registerPhpFunctionNS('urn:foo', 'strtolower', 'strtolower'); 39var_dump($xpath->query('//a[foo:strtolower(string(@href)) = "https://php.net"]')); 40 41echo "--- Legit cases: trampoline callable ---\n"; 42 43$xpath->registerPhpFunctionNS('urn:foo', 'test', TrampolineClass::test(...)); 44var_dump($xpath->query('//a[foo:test(string(@href)) = "https://php.net"]')); 45 46echo "--- Legit cases: instance class method callable ---\n"; 47 48$state = new StatefulClass; 49$xpath->registerPhpFunctionNS('urn:foo', 'test', $state->test(...)); 50var_dump($xpath->query('//a[foo:test(string(@href))]')); 51var_dump($state->state); 52 53echo "--- Legit cases: global function callable that returns nothing ---\n"; 54 55$xpath->registerPhpFunctionNS('urn:foo', 'test', var_dump(...)); 56$xpath->query('//a[foo:test(string(@href))]'); 57 58echo "--- Legit cases: multiple namespaces ---\n"; 59 60$xpath->registerNamespace('bar', 'urn:bar'); 61$xpath->registerPhpFunctionNS('urn:bar', 'test', 'strtolower'); 62var_dump($xpath->query('//a[bar:test(string(@href)) = "https://php.net"]')); 63 64?> 65--EXPECT-- 66--- Legit cases: global function callable --- 67object(DOMNodeList)#5 (1) { 68 ["length"]=> 69 int(1) 70} 71--- Legit cases: string callable --- 72object(DOMNodeList)#5 (1) { 73 ["length"]=> 74 int(1) 75} 76--- Legit cases: trampoline callable --- 77string(4) "test" 78array(1) { 79 [0]=> 80 string(15) "https://PHP.net" 81} 82object(DOMNodeList)#3 (1) { 83 ["length"]=> 84 int(0) 85} 86--- Legit cases: instance class method callable --- 87object(DOMNodeList)#6 (1) { 88 ["length"]=> 89 int(1) 90} 91array(1) { 92 [0]=> 93 array(2) { 94 [0]=> 95 string(4) "test" 96 [1]=> 97 string(15) "https://PHP.net" 98 } 99} 100--- Legit cases: global function callable that returns nothing --- 101string(15) "https://PHP.net" 102--- Legit cases: multiple namespaces --- 103object(DOMNodeList)#5 (1) { 104 ["length"]=> 105 int(1) 106} 107