Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1e55758

Browse files
committed
Prototype XSLTProcessor::transformToStream()
1 parent 7f27a81 commit 1e55758

File tree

6 files changed

+185
-1
lines changed

6 files changed

+185
-1
lines changed

‎ext/xsl/php_xsl.stub.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ public function importStylesheet(object $stylesheet): bool {}
9191
*/
9292
public function transformToDoc(object $document, ?string $returnClass = null): object|false {}
9393

94+
/**
95+
* @param DOMDocument|Dom\Document|SimpleXMLElement $document
96+
* @param resource $stream
97+
*/
98+
public function transformToStream(object $document, $stream, ?string $encoding = null): int {}
99+
94100
/**
95101
* @param DOMDocument|Dom\Document|SimpleXMLElement $document
96102
* @tentative-return-type

‎ext/xsl/php_xsl_arginfo.h

Lines changed: 9 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎ext/xsl/tests/transform_to_stream.phpt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
XSLTProcessor::transformToStream() function - normal
3+
--EXTENSIONS--
4+
xsl
5+
--FILE--
6+
<?php
7+
include("prepare.inc");
8+
$proc->importStylesheet($xsl);
9+
10+
$stream = fopen('php://output', 'w');
11+
$written = $proc->transformToStream($dom, $stream);
12+
fclose($stream);
13+
14+
echo "\n";
15+
var_dump($written);
16+
17+
$stream = fopen('php://output', 'w');
18+
$written = $proc->transformToStream($dom, $stream, 'iso-8859-1');
19+
fclose($stream);
20+
21+
echo "\n";
22+
var_dump($written);
23+
?>
24+
--EXPECT--
25+
<?xml version="1.0" encoding="iso-8859-1"?>
26+
<html><body>bar
27+
a1 b1 c1 <br/>
28+
a2 c2 <br/>
29+
ä3 b3 c3 <br/>
30+
</body></html>
31+
int(120)
32+
<?xml version="1.0" encoding="iso-8859-1"?>
33+
<html><body>bar
34+
a1 b1 c1 <br/>
35+
a2 c2 <br/>
36+
ä3 b3 c3 <br/>
37+
</body></html>
38+
int(119)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
--TEST--
2+
XSLTProcessor::transformToStream() function - broken stream
3+
--EXTENSIONS--
4+
xsl
5+
--FILE--
6+
<?php
7+
class MyStream {
8+
public $context;
9+
private bool $first = true;
10+
11+
public function stream_write(string $data): int {
12+
if ($this->first) {
13+
$this->first = false;
14+
var_dump($data);
15+
}
16+
throw new Error("broken");
17+
}
18+
19+
public function stream_open(string $path, string $mode, int $options, ?string &$opened_path) {
20+
return true;
21+
}
22+
23+
public function stream_close(): void {
24+
}
25+
26+
public function stream_eof(): bool {
27+
return !$this->first;
28+
}
29+
}
30+
31+
stream_wrapper_register("foo", MyStream::class);
32+
33+
include("prepare.inc");
34+
$proc->importStylesheet($xsl);
35+
36+
$stream = fopen('foo://', 'w');
37+
stream_set_chunk_size($stream, 4);
38+
$written = $proc->transformToStream($dom, $stream);
39+
fclose($stream);
40+
41+
echo "\n";
42+
var_dump($written);
43+
?>
44+
--EXPECTF--
45+
string(4) "<?xm"
46+
47+
Fatal error: Uncaught Error: broken in %s:%d
48+
Stack trace:
49+
#0 [internal function]: MyStream->stream_write('<?xm')
50+
#1 %s(%d): XSLTProcessor->transformToStream(Object(DOMDocument), Resource id #%d)
51+
#2 {main}
52+
thrown in %s on line %d
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
XSLTProcessor::transformToStream() function - errors
3+
--EXTENSIONS--
4+
xsl
5+
--FILE--
6+
<?php
7+
include("prepare.inc");
8+
$proc->importStylesheet($xsl);
9+
10+
$stream = fopen('php://output', 'w');
11+
try {
12+
$proc->transformToStream($dom, $stream, 'nope');
13+
} catch (ValueError $e) {
14+
echo $e->getMessage(), "\n";
15+
}
16+
fclose($stream);
17+
?>
18+
--EXPECT--
19+
XSLTProcessor::transformToStream(): Argument #3 ($encoding) is not a valid document encoding

‎ext/xsl/xsltprocessor.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "php.h"
2323
#include "php_xsl.h"
24+
#include "Zend/zend_exceptions.h"
2425
#include <libxslt/variables.h>
2526
#include "ext/libxml/php_libxml.h"
2627
#include "ext/dom/namespace_compat.h"
@@ -481,6 +482,66 @@ PHP_METHOD(XSLTProcessor, transformToDoc)
481482
}
482483
/* }}} end XSLTProcessor::transformToDoc */
483484

485+
static int xsl_stream_write(void *context, const char *buffer, int len)
486+
{
487+
zend_resource *resource = context;
488+
if (EXPECTED(resource->ptr)) {
489+
php_stream *stream = resource->ptr;
490+
return php_stream_write(stream, buffer, len);
491+
}
492+
return -1;
493+
}
494+
495+
PHP_METHOD(XSLTProcessor, transformToStream)
496+
{
497+
zval *docp, *stream_zv;
498+
php_stream *stream;
499+
const char *encoding = NULL;
500+
size_t encoding_len;
501+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "or|p!", &docp, &stream_zv, &encoding, &encoding_len) == FAILURE) {
502+
RETURN_THROWS();
503+
}
504+
505+
php_stream_from_res(stream, Z_RES_P(stream_zv));
506+
507+
xmlCharEncodingHandlerPtr handler = NULL;
508+
if (encoding) {
509+
handler = xmlFindCharEncodingHandler(encoding);
510+
if (UNEXPECTED(!handler)) {
511+
zend_argument_value_error(3, "is not a valid document encoding");
512+
RETURN_THROWS();
513+
}
514+
}
515+
516+
xsl_object *intern = Z_XSL_P(ZEND_THIS);
517+
xsltStylesheetPtr sheetp = intern->ptr;
518+
519+
xmlOutputBufferPtr out = xmlOutputBufferCreateIO(xsl_stream_write, NULL, stream->res, handler);
520+
if (UNEXPECTED(!out)) {
521+
zend_throw_error(zend_ce_exception, "Failed to create output buffer");
522+
RETURN_THROWS();
523+
}
524+
525+
xmlDocPtr newdocp = php_xsl_apply_stylesheet(ZEND_THIS, intern, sheetp, docp);
526+
527+
int ret = -1;
528+
if (newdocp) {
529+
ret = xsltSaveResultTo(out, newdocp, sheetp);
530+
xmlFreeDoc(newdocp);
531+
}
532+
533+
xmlOutputBufferClose(out);
534+
535+
if (ret < 0) {
536+
if (!EG(exception)) {
537+
zend_throw_error(zend_ce_exception, "Failed to transform and write document");
538+
}
539+
RETURN_THROWS();
540+
}
541+
542+
RETURN_LONG(ret);
543+
}
544+
484545
/* {{{ */
485546
PHP_METHOD(XSLTProcessor, transformToUri)
486547
{

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /