1--TEST-- 2registerPHPFunctionNS() function - legit cases 3--EXTENSIONS-- 4xsl 5--FILE-- 6<?php 7 8class TrampolineClass { 9 public static function __callStatic(string $name, array $arguments): mixed { 10 var_dump($name, $arguments); 11 return "foo"; 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 24function createProcessor($inputs) { 25 $xsl = new DomDocument(); 26 $xsl->loadXML('<?xml version="1.0" encoding="iso-8859-1" ?> 27 <xsl:stylesheet version="1.0" 28 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 29 xmlns:foo="urn:foo" 30 xmlns:bar="urn:bar"> 31 <xsl:template match="//a">' 32 . implode('', array_map(fn($input) => '<xsl:value-of select="' . $input . '" />', $inputs)) . 33 '</xsl:template> 34 </xsl:stylesheet>'); 35 36 $proc = new XSLTProcessor(); 37 $proc->importStylesheet($xsl); 38 return $proc; 39} 40 41$inputdom = new DomDocument(); 42$inputdom->loadXML('<?xml version="1.0" encoding="iso-8859-1"?><a href="https://php.net">hello</a>'); 43 44echo "--- Legit cases: none ---\n"; 45 46$proc = createProcessor(["foo:var_dump(string(@href))"]); 47try { 48 $proc->transformToXml($inputdom); 49} catch (Error $e) { 50 echo $e->getMessage(), "\n"; 51} 52 53echo "--- Legit cases: global function callable ---\n"; 54 55$proc = createProcessor(["foo:var_dump(string(@href))"]); 56$proc->registerPHPFunctionNS('urn:foo', 'var_dump', var_dump(...)); 57$proc->transformToXml($inputdom); 58 59echo "--- Legit cases: global string callable ---\n"; 60 61$proc = createProcessor(["foo:var_dump(string(@href))"]); 62$proc->registerPHPFunctionNS('urn:foo', 'var_dump', 'var_dump'); 63$proc->transformToXml($inputdom); 64 65echo "--- Legit cases: trampoline callable ---\n"; 66 67$proc = createProcessor(["foo:trampoline(string(@href))"]); 68$proc->registerPHPFunctionNS('urn:foo', 'trampoline', TrampolineClass::test(...)); 69var_dump($proc->transformToXml($inputdom)); 70 71echo "--- Legit cases: instance class method callable ---\n"; 72 73$state = new StatefulClass; 74$proc = createProcessor(["foo:test(string(@href))"]); 75$proc->registerPHPFunctionNS('urn:foo', 'test', $state->test(...)); 76var_dump($proc->transformToXml($inputdom)); 77var_dump($state->state); 78 79echo "--- Legit cases: multiple namespaces ---\n"; 80 81$proc = createProcessor(["foo:test(string(@href))", "bar:test(string(@href))"]); 82$proc->registerPHPFunctionNS('urn:foo', 'test', strrev(...)); 83$proc->registerPHPFunctionNS('urn:bar', 'test', strtoupper(...)); 84var_dump($proc->transformToXml($inputdom)); 85 86?> 87--EXPECTF-- 88--- Legit cases: none --- 89 90Warning: XSLTProcessor::transformToXml(): xmlXPathCompOpEval: function var_dump not found in %s on line %d 91 92Warning: XSLTProcessor::transformToXml(): Unregistered function in %s on line %d 93 94Warning: XSLTProcessor::transformToXml(): runtime error: file %s line 6 element value-of in %s on line %d 95 96Warning: XSLTProcessor::transformToXml(): XPath evaluation returned no result. in %s on line %d 97--- Legit cases: global function callable --- 98string(15) "https://php.net" 99--- Legit cases: global string callable --- 100string(15) "https://php.net" 101--- Legit cases: trampoline callable --- 102string(4) "test" 103array(1) { 104 [0]=> 105 string(15) "https://php.net" 106} 107string(26) "<?xml version="1.0"?> 108foo 109" 110--- Legit cases: instance class method callable --- 111string(38) "<?xml version="1.0"?> 112https://php.net 113" 114array(1) { 115 [0]=> 116 array(2) { 117 [0]=> 118 string(4) "test" 119 [1]=> 120 string(15) "https://php.net" 121 } 122} 123--- Legit cases: multiple namespaces --- 124string(53) "<?xml version="1.0"?> 125ten.php//:sptthHTTPS://PHP.NET 126" 127