Skip to content

Commit de141f2

Browse files
committed
Implement Dom\HTMLDocument::createFromStream()
1 parent d162401 commit de141f2

File tree

5 files changed

+115
-2
lines changed

5 files changed

+115
-2
lines changed

ext/dom/html_document.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -974,10 +974,12 @@ static void dom_html_document_create_from_stream(
974974
const char *filename
975975
)
976976
{
977+
ZEND_ASSERT(stream != NULL);
978+
977979
php_dom_private_data *private_data = NULL;
978980

979981
dom_lexbor_libxml2_bridge_application_data application_data;
980-
application_data.input_name = filename;
982+
application_data.input_name = filename ? filename : "Entity";
981983
application_data.current_total_offset = 0;
982984
application_data.html_no_implied = options & HTML_PARSE_NOIMPLIED;
983985
dom_reset_line_column_cache(&application_data.cache_tokenizer);
@@ -1202,6 +1204,34 @@ PHP_METHOD(Dom_HTMLDocument, createFromFile)
12021204
php_stream_close(stream);
12031205
}
12041206

1207+
PHP_METHOD(Dom_HTMLDocument, createFromStream)
1208+
{
1209+
php_stream *stream;
1210+
zval *stream_zv;
1211+
const char *document_uri = NULL;
1212+
const char *override_encoding = NULL;
1213+
size_t override_encoding_len, document_uri_len;
1214+
zend_long options = 0;
1215+
if (zend_parse_parameters(
1216+
ZEND_NUM_ARGS(),
1217+
"r|p!lp!",
1218+
&stream_zv,
1219+
&document_uri,
1220+
&document_uri_len,
1221+
&options,
1222+
&override_encoding,
1223+
&override_encoding_len
1224+
) == FAILURE) {
1225+
RETURN_THROWS();
1226+
}
1227+
1228+
php_stream_from_res(stream, Z_RES_P(stream_zv));
1229+
1230+
dom_html_document_create_from_stream(
1231+
return_value, stream, options, override_encoding, override_encoding_len, NULL, document_uri
1232+
);
1233+
}
1234+
12051235
static zend_result dom_write_output_smart_str(void *ctx, const char *buf, size_t size)
12061236
{
12071237
smart_str_appendl((smart_str *) ctx, buf, size);

ext/dom/php_dom.stub.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,6 +2042,9 @@ public static function createEmpty(string $encoding = "UTF-8"): HTMLDocument {}
20422042

20432043
public static function createFromFile(string $path, int $options = 0, ?string $overrideEncoding = null): HTMLDocument {}
20442044

2045+
/** @param resource $stream */
2046+
public static function createFromStream($stream, ?string $documentURI = null, int $options = 0, ?string $overrideEncoding = null): HTMLDocument {}
2047+
20452048
public static function createFromString(string $source, int $options = 0, ?string $overrideEncoding = null): HTMLDocument {}
20462049

20472050
/** @implementation-alias Dom\XMLDocument::saveXml */

ext/dom/php_dom_arginfo.h

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Dom\HTMLDocument::createFromStream() - from memory
3+
--EXTENSIONS--
4+
dom
5+
--FILE--
6+
<?php
7+
8+
$tmp = fopen("php://memory", "w+");
9+
fwrite($tmp, "<!DOCTYPE html><html><p>Hello world</p></html>");
10+
rewind($tmp);
11+
$dom1 = Dom\HTMLDocument::createFromStream($tmp);
12+
rewind($tmp);
13+
$dom2 = Dom\HTMLDocument::createFromStream($tmp, "http://example.com");
14+
fclose($tmp);
15+
16+
var_dump($dom1->documentURI);
17+
var_dump($dom2->documentURI);
18+
19+
echo $dom1->saveHtml(), "\n";
20+
echo $dom2->saveHtml(), "\n";
21+
22+
?>
23+
--EXPECT--
24+
string(11) "about:blank"
25+
string(18) "http://example.com"
26+
<!DOCTYPE html><html><head></head><body><p>Hello world</p></body></html>
27+
<!DOCTYPE html><html><head></head><body><p>Hello world</p></body></html>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
--TEST--
2+
Dom\HTMLDocument::createFromStream() - broken stream
3+
--EXTENSIONS--
4+
dom
5+
--FILE--
6+
<?php
7+
8+
class MyStream {
9+
public $context;
10+
private bool $first = true;
11+
12+
public function stream_read(int $count): string|false {
13+
if ($this->first) {
14+
$this->first = false;
15+
return "<!DOCTYPE html><html><p>Hello";
16+
}
17+
throw new Error("broken");
18+
}
19+
20+
public function stream_open(string $path, string $mode, int $options, ?string &$opened_path) {
21+
return true;
22+
}
23+
24+
public function stream_close(): void {
25+
}
26+
27+
public function stream_eof(): bool {
28+
return !$this->first;
29+
}
30+
}
31+
32+
stream_wrapper_register("foo", MyStream::class);
33+
34+
$tmp = fopen("foo://", "r+");
35+
try {
36+
$dom = Dom\HTMLDocument::createFromStream($tmp);
37+
} catch (Error $e) {
38+
echo $e->getMessage(), "\n";
39+
}
40+
fclose($tmp);
41+
42+
?>
43+
--EXPECT--
44+
broken

0 commit comments

Comments
 (0)