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

View File

@ -15,6 +15,7 @@
* `SS_Filterable`, `SS_Limitable` and `SS_Sortable` now explicitly extend `SS_List` * `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. * `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. * `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 #### Deprecated classes/methods removed

View File

@ -140,6 +140,21 @@ class ErrorControlChainTest extends SapphireTest {
->executeInSubprocess(); ->executeInSubprocess();
$this->assertEquals('Done', $out); $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() { function testExceptionSuppression() {