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