diff --git a/lib/Service.php b/lib/Service.php index 747587e..1eca0e4 100644 --- a/lib/Service.php +++ b/lib/Service.php @@ -78,10 +78,22 @@ public function getReader(): Reader /** * Returns a fresh xml writer. + * + * @param ?resource $streamOutput Only available with PHP >= 8.4 */ - public function getWriter(): Writer + public function getWriter($streamOutput = null): Writer { - $w = new Writer(); + if (null !== $streamOutput) { + if (!is_resource($streamOutput)) { + throw new \InvalidArgumentException('$streamOutput must be a resource'); + } + if (PHP_VERSION_ID < 80400) { + throw new \RuntimeException('Service::getWriter() requires PHP 8.4 or higher'); + } + $w = Writer::toStream($streamOutput); + } else { + $w = new Writer(); + } $w->namespaceMap = $this->namespaceMap; $w->classMap = $this->classMap; @@ -226,6 +238,38 @@ public function write(string $rootElementName, $value, ?string $contextUri = nul return $w->outputMemory(); } + /** + * Generates an XML document in one go. + * + * The $rootElement must be specified in clark notation. + * The value must be a string, an array or an object implementing + * XmlSerializable. Basically, anything that's supported by the Writer + * object. + * + * $contextUri can be used to specify a sort of 'root' of the PHP application, + * in case the xml document is used as a http response. + * + * This allows an implementor to easily create URI's relative to the root + * of the domain. + * + * @param resource $outputStream + * @param string|array|object|XmlSerializable $value + * + * @warning Only available with > PHP 8.4 + */ + public function writeStream($outputStream, string $rootElementName, $value, ?string $contextUri = null): void + { + if (PHP_VERSION_ID < 80400) { + throw new \RuntimeException('Service::writeStream() requires PHP 8.4 or higher'); + } + + $w = $this->getWriter($outputStream); + $w->contextUri = $contextUri; + $w->setIndent(true); + $w->startDocument(); + $w->writeElement($rootElementName, $value); + } + /** * Map an XML element to a PHP class. * diff --git a/tests/Sabre/Xml/ServiceTest.php b/tests/Sabre/Xml/ServiceTest.php index c300060..c9db7ff 100644 --- a/tests/Sabre/Xml/ServiceTest.php +++ b/tests/Sabre/Xml/ServiceTest.php @@ -240,6 +240,39 @@ public function testWrite(): void value +XML; + self::assertEquals( + $expected, + $result + ); + } + + #[Depends('testGetWriter')] + public function testWriteStream(): void + { + if (PHP_VERSION_ID < 80400) { + $this->markTestSkipped('Requires PHP 8.4 or higher'); + } + $util = new Service(); + $util->namespaceMap = [ + 'http://sabre.io/ns' => 'stdClass', + ]; + + $stream = fopen('php://temp', 'w+'); + $this->assertNotFalse($stream); + $util->writeStream($stream, '{http://sabre.io/ns}root', [ + '{http://sabre.io/ns}child' => 'value', + ]); + + rewind($stream); + $result = stream_get_contents($stream); + + $expected = << + + value + + XML; self::assertEquals( $expected,