Merge pull request #3512 from tractorcow/pulls/3.2/exceptions

BUG ErrorControlChain now supports exception handling
This commit is contained in:
Sean Harvey 2014-10-06 15:22:11 +13:00
commit b4df2aa80f
3 changed files with 74 additions and 1 deletions

View File

@ -17,9 +17,25 @@
class ErrorControlChain {
public static $fatal_errors = null; // Initialised after class definition
/**
* Is there an error?
*
* @var bool
*/
protected $error = false;
/**
* List of steps
*
* @var array
*/
protected $steps = array();
/**
* True if errors should be hidden
*
* @var bool
*/
protected $suppression = true;
/** We can't unregister_shutdown_function, so this acts as a flag to enable handling */
@ -28,6 +44,18 @@ class ErrorControlChain {
/** We overload display_errors to hide errors during execution, so we need to remember the original to restore to */
protected $originalDisplayErrors = null;
/**
* Any exceptions passed through the chain
*
* @var Exception
*/
protected $lastException = null;
/**
* Determine if an error has been found
*
* @return bool
*/
public function hasErrored() {
return $this->error;
}
@ -57,19 +85,43 @@ class ErrorControlChain {
return $this;
}
/**
* Request that the callback is invoked if not errored
*
* @param callable $callback
* @return $this
*/
public function thenWhileGood($callback) {
return $this->then($callback, false);
}
/**
* Request that the callback is invoked on error
*
* @param callable $callback
* @return $this
*/
public function thenIfErrored($callback) {
return $this->then($callback, true);
}
/**
* Request that the callback is invoked always
*
* @param callable $callback
* @return $this
*/
public function thenAlways($callback) {
return $this->then($callback, null);
}
/**
* Return true if the last error was fatal
*
* @return boolean
*/
protected function lastErrorWasFatal() {
if($this->lastException) return true;
$error = error_get_last();
return $error && ($error['type'] & self::$fatal_errors) != 0;
}
@ -122,7 +174,12 @@ class ErrorControlChain {
$step = array_shift($this->steps);
if ($step['onErrorState'] === null || $step['onErrorState'] === $this->error) {
call_user_func($step['callback'], $this);
try {
call_user_func($step['callback'], $this);
} catch (Exception $ex) {
$this->lastException = $ex;
throw $ex;
}
}
$this->step();

View File

@ -15,6 +15,7 @@
* `SS_Filterable`, `SS_Limitable` and `SS_Sortable` now explicitly extend `SS_List`
* `Convert::html2raw` no longer wraps text by default and can decode single quotes.
* `Mailer` no longer calls `xml2raw` on all email subject line, and now must be passed in via plain text.
* `ErrorControlChain` now supports reload on exceptions
#### Deprecated classes/methods removed

View File

@ -140,6 +140,21 @@ class ErrorControlChainTest extends SapphireTest {
->executeInSubprocess();
$this->assertEquals('Done', $out);
// Exceptions
$chain = new ErrorControlChainTest_Chain();
list($out, $code) = $chain
->then(function(){
throw new Exception("bob");
})
->thenIfErrored(function(){
echo "Done";
})
->executeInSubprocess();
$this->assertEquals('Done', $out);
}
function testExceptionSuppression() {