-
Notifications
You must be signed in to change notification settings - Fork 41
Description
Version
Please add the exact versions used for each of the following:
- WP Emerge: latest
- WordPress: 5.6
- PHP: 7.3
Expected behavior
When an exception occurs inside rendering a view, all output buffers are cleared, and an exception is thrown to render an error page appropriately.
Actual behaviour
Right now, any error that happens inside view rendering will cause any HTML before the error to be printed to the client.
Steps to reproduce (in case of a bug)
- Create a route:
\App\App::route()->get()->url('foo')->handle(function () {
return \App\App::view('view.php');
}); - Create a view like this:
<?php
?>
<h2> Foobar</h2>
<?php
non_existing_function();
?>-
Turn on
WP_DEBUG(optional) -
Visit
yoursite.com/foo -
See
Foobarin the error page html.
Comments
The reason this happens can be found inside the PhpView class
The toString method needs to have some form of error handling that resets the buffered content. If not PHP will automatically clear and print the output when an exception occurs and the script shuts down.
public function toString() {
if ( empty( $this->getName() ) ) {
throw new ViewException( 'View must have a name.' );
}
if ( empty( $this->getFilepath() ) ) {
throw new ViewException( 'View must have a filepath.' );
}
$this->engine->pushLayoutContent( $this );
if ( $this->getLayout() !== null ) {
// ERROR HAPPENS HERE
return $this->getLayout()->toString();
}
return $this->engine->getLayoutContent();
}A possible fix would be changing the relevant part to something like this:
public function toString() {
// left out for brevity
ob_start();
try {
if ( $this->getLayout() !== null ) {
// ERROR HAPPENS HERE
return $this->getLayout()->toString();
}
$this->engine->getLayoutContent();
}
catch ( Throwbable $e ) {
ob_end_clean();
throw new ViewException();
}
return ob_get_clean();
}