Merge 3.1 into 3.2

This commit is contained in:
Damian Mooyman 2016-05-18 17:25:42 +12:00
commit 8dfeeb0eb6
2 changed files with 86 additions and 38 deletions

View File

@ -77,12 +77,34 @@ class ErrorControlChain {
*/ */
public function setSuppression($suppression) { public function setSuppression($suppression) {
$this->suppression = (bool)$suppression; $this->suppression = (bool)$suppression;
// Don't modify errors unless handling fatal errors, and if errors were // If handling fatal errors, conditionally disable, or restore error display
// originally allowed to be displayed. // Note: original value of display_errors could also evaluate to "off"
if ($this->handleFatalErrors && $this->originalDisplayErrors) { if ($this->handleFatalErrors) {
ini_set('display_errors', !$suppression); if($suppression) {
$this->setDisplayErrors(0);
} else {
$this->setDisplayErrors($this->originalDisplayErrors);
} }
} }
}
/**
* Set display_errors
*
* @param mixed $errors
*/
protected function setDisplayErrors($errors) {
ini_set('display_errors', $errors);
}
/**
* Get value of display_errors ini value
*
* @return mixed
*/
protected function getDisplayErrors() {
return ini_get('display_errors');
}
/** /**
* Add this callback to the chain of callbacks to call along with the state * Add this callback to the chain of callbacks to call along with the state
@ -178,7 +200,7 @@ class ErrorControlChain {
register_shutdown_function(array($this, 'handleFatalError')); register_shutdown_function(array($this, 'handleFatalError'));
$this->handleFatalErrors = true; $this->handleFatalErrors = true;
$this->originalDisplayErrors = ini_get('display_errors'); $this->originalDisplayErrors = $this->getDisplayErrors();
$this->setSuppression($this->suppression); $this->setSuppression($this->suppression);
$this->step(); $this->step();
@ -202,7 +224,7 @@ class ErrorControlChain {
else { else {
// Now clean up // Now clean up
$this->handleFatalErrors = false; $this->handleFatalErrors = false;
ini_set('display_errors', $this->originalDisplayErrors); $this->setDisplayErrors($this->originalDisplayErrors);
} }
} }
} }

View File

@ -8,6 +8,30 @@
*/ */
class ErrorControlChainTest_Chain extends ErrorControlChain { class ErrorControlChainTest_Chain extends ErrorControlChain {
protected $displayErrors = 'STDERR';
/**
* Modify method visibility to public for testing
*
* @return string
*/
public function getDisplayErrors()
{
// Protect manipulation of underlying php_ini values
return $this->displayErrors;
}
/**
* Modify method visibility to public for testing
*
* @param mixed $errors
*/
public function setDisplayErrors($errors)
{
// Protect manipulation of underlying php_ini values
$this->displayErrors = $errors;
}
// Change function visibility to be testable directly // Change function visibility to be testable directly
public function translateMemstring($memstring) { public function translateMemstring($memstring) {
return parent::translateMemstring($memstring); return parent::translateMemstring($memstring);
@ -63,10 +87,7 @@ require_once '$classpath';
class ErrorControlChainTest extends SapphireTest { class ErrorControlChainTest extends SapphireTest {
protected $displayErrors = null;
function setUp() { function setUp() {
$this->displayErrors = (bool)ini_get('display_errors');
// Check we can run PHP at all // Check we can run PHP at all
$null = is_writeable('/dev/null') ? '/dev/null' : 'NUL'; $null = is_writeable('/dev/null') ? '/dev/null' : 'NUL';
@ -80,50 +101,55 @@ class ErrorControlChainTest extends SapphireTest {
parent::setUp(); parent::setUp();
} }
public function tearDown() {
if($this->displayErrors !== null) {
ini_set('display_errors', $this->displayErrors);
$this->displayErrors = null;
}
parent::tearDown(); // TODO: Change the autogenerated stub
}
function testErrorSuppression() { function testErrorSuppression() {
// Errors disabled by default // Errors disabled by default
ini_set('display_errors', false); $chain = new ErrorControlChainTest_Chain();
$chain = new ErrorControlChain(); $chain->setDisplayErrors('Off'); // mocks display_errors: Off
$initialValue = null;
$whenNotSuppressed = null; $whenNotSuppressed = null;
$whenSuppressed = null; $whenSuppressed = null;
$chain->then(function($chain) use(&$whenNotSuppressed, &$whenSuppressed) { $chain->then(
$chain->setSuppression(true); function(ErrorControlChainTest_Chain $chain)
$whenSuppressed = ini_get('display_errors'); use(&$initialValue, &$whenNotSuppressed, &$whenSuppressed) {
$initialValue = $chain->getDisplayErrors();
$chain->setSuppression(false); $chain->setSuppression(false);
$whenNotSuppressed = ini_get('display_errors'); $whenNotSuppressed = $chain->getDisplayErrors();
})->execute(); $chain->setSuppression(true);
$whenSuppressed = $chain->getDisplayErrors();
}
)->execute();
// Disabled errors never un-disable // Disabled errors never un-disable
$this->assertFalse((bool)$whenNotSuppressed); $this->assertEquals(0, $initialValue); // Chain starts suppressed
$this->assertFalse((bool)$whenSuppressed); $this->assertEquals(0, $whenSuppressed); // false value used internally when suppressed
$this->assertEquals('Off', $whenNotSuppressed); // false value set by php ini when suppression lifted
$this->assertEquals('Off', $chain->getDisplayErrors()); // Correctly restored after run
// Errors enabled by default // Errors enabled by default
ini_set('display_errors', true); $chain = new ErrorControlChainTest_Chain();
$chain = new ErrorControlChain(); $chain->setDisplayErrors('Yes'); // non-falsey ini value
$initialValue = null;
$whenNotSuppressed = null; $whenNotSuppressed = null;
$whenSuppressed = null; $whenSuppressed = null;
$chain->then(function($chain) use(&$whenNotSuppressed, &$whenSuppressed) { $chain->then(
function(ErrorControlChainTest_Chain $chain)
use(&$initialValue, &$whenNotSuppressed, &$whenSuppressed) {
$initialValue = $chain->getDisplayErrors();
$chain->setSuppression(true); $chain->setSuppression(true);
$whenSuppressed = ini_get('display_errors'); $whenSuppressed = $chain->getDisplayErrors();
$chain->setSuppression(false); $chain->setSuppression(false);
$whenNotSuppressed = ini_get('display_errors'); $whenNotSuppressed = $chain->getDisplayErrors();
})->execute(); }
)->execute();
// Errors can be suppressed an un-suppressed when initially enabled // Errors can be suppressed an un-suppressed when initially enabled
$this->assertTrue((bool)$whenNotSuppressed); $this->assertEquals(0, $initialValue); // Chain starts suppressed
$this->assertFalse((bool)$whenSuppressed); $this->assertEquals(0, $whenSuppressed); // false value used internally when suppressed
$this->assertEquals('Yes', $whenNotSuppressed); // false value set by php ini when suppression lifted
$this->assertEquals('Yes', $chain->getDisplayErrors()); // Correctly restored after run
// Fatal error // Fatal error
$chain = new ErrorControlChainTest_Chain(); $chain = new ErrorControlChainTest_Chain();
list($out, $code) = $chain list($out, $code) = $chain