Skip to content

writeHTML5() returns NULL instead of the DOMQuery, and reports an unwritable path as a raw TypeError #80

Description

@jakejackson1

Guidelines

Description of the bug

writeHTML5() is the odd one out among the four write* methods in two ways.

1. It does not return the DOMQuery, so it cannot be chained. writeXML(), writeHTML() and writeXHTML() all return $this; writeHTML5() returns NULL on both code paths (src/DOMQuery.php:1363-1375):

public function writeHTML5($path = null)
{
	$html5 = new HTML5();
	if ($path === null) {
		print $html5->saveHTML($this->document);

		return;                          // <-- no $this
	}

	$html5->save($this->document, $path);
}                                        // <-- no $this

Since html5qp() is the recommended entry point for HTML, this is the write* method most people reach for, and it is the only one that terminates a chain.

2. An unwritable path surfaces as a raw TypeError, not a QueryPath exception. The other three install an error handler and throw QueryPath\IOException (writeXML(), writeXHTML()) or QueryPath\ParseException (writeHTML()), so catch (\QueryPath\Exception $e) — the documented pattern — covers them. writeHTML5() has no handler, so the failure escapes from inside masterminds/html5 as:

TypeError: fwrite(): Argument #1 ($stream) must be of type resource, false given

Suggested fix

Return $this on both paths, and wrap the save() call the way writeXML() does so a failure becomes an IOException.

Adding the return value is backwards compatible — nothing can currently depend on the NULL, since there is nothing useful to do with it.

Also note the method has no @return tag at all, which is presumably how the inconsistency went unnoticed.

QueryPath version

4.2.0 (also reproduces on main at bed5d2c)

PHP Version and environment (server type, cli provider etc., enclosing libraries and their respective versions)

PHP 8.3.16 CLI (macOS, Homebrew). Not PHP-8 specific — the cause is present on every supported version.

Minimal reproducible PHP+HTML snippet to replicate bug

<?php
require __DIR__ . '/vendor/autoload.php';

$qp = html5qp('<p>x</p>');

var_dump(get_class($qp->writeXML(tempnam(sys_get_temp_dir(), 'qp'))));  // QueryPath\DOMQuery
var_dump($qp->writeHTML5(tempnam(sys_get_temp_dir(), 'qp')));           // NULL - cannot chain

// And for the error handling:
try {
    $qp->writeHTML5('/nonexistent-dir-xyz/out.html');
} catch (\QueryPath\Exception $e) {
    echo "caught as QueryPath exception\n";       // not reached
}
// Uncaught TypeError: fwrite(): Argument #1 ($stream) must be of type resource, false given

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions