mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge 3.3 into 3
# Conflicts: # admin/javascript/LeftAndMain.EditForm.js
This commit is contained in:
commit
303f695751
@ -47,6 +47,14 @@
|
||||
ignoreFieldSelector: '.no-change-track, .ss-upload :input, .cms-navigator :input'
|
||||
},
|
||||
|
||||
/**
|
||||
* Variable: ValidationErrorShown
|
||||
* Boolean for tracking whether a validation error has been already been shown. Used because tabs can
|
||||
* sometimes be inadvertently initialised multiple times, but we don't want duplicate messages
|
||||
* (Boolean)
|
||||
*/
|
||||
ValidationErrorShown: false,
|
||||
|
||||
/**
|
||||
* Constructor: onmatch
|
||||
*/
|
||||
@ -77,6 +85,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Reset error display
|
||||
this.setValidationErrorShown(false);
|
||||
|
||||
// TODO
|
||||
// // Rewrite # links
|
||||
// html = html.replace(/(<a[^>]+href *= *")#/g, '$1' + window.location.href.replace(/#.*$/,'') + '#');
|
||||
@ -84,15 +95,33 @@
|
||||
// // Rewrite iframe links (for IE)
|
||||
// html = html.replace(/(<iframe[^>]*src=")([^"]+)("[^>]*>)/g, '$1' + $('base').attr('href') + '$2$3');
|
||||
|
||||
this._super();
|
||||
},
|
||||
'from .cms-tabset': {
|
||||
onafterredrawtabs: function () {
|
||||
// Show validation errors if necessary
|
||||
if(this.hasClass('validationerror')) {
|
||||
// Ensure the first validation error is visible
|
||||
var tabError = this.find('.message.validation, .message.required').first().closest('.tab');
|
||||
$('.cms-container').clearCurrentTabState(); // clear state to avoid override later on
|
||||
tabError.closest('.ss-tabset').tabs('option', 'active', tabError.index('.tab'));
|
||||
|
||||
// Attempt #1: Look for nearest .ss-tabset (usually nested deeper underneath a .cms-tabset).
|
||||
var $tabSet = tabError.closest('.ss-tabset');
|
||||
|
||||
// Attempt #2: Next level in tab-ception, try to select the tab within this higher level .cms-tabset if possible
|
||||
if (!$tabSet.length) {
|
||||
$tabSet = tabError.closest('.cms-tabset');
|
||||
}
|
||||
|
||||
this._super();
|
||||
if ($tabSet.length) {
|
||||
$tabSet.tabs('option', 'active', tabError.index('.tab'));
|
||||
} else if (!this.getValidationErrorShown()) {
|
||||
// Ensure that this error message popup won't be added more than once
|
||||
this.setValidationErrorShown(true);
|
||||
errorMessage(ss.i18n._t('ModelAdmin.VALIDATIONERROR', 'Validation Error'));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onremove: function() {
|
||||
this.changetracker('destroy');
|
||||
|
@ -1450,6 +1450,8 @@ jQuery.noConflict();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.trigger('afterredrawtabs');
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -77,13 +77,35 @@ class ErrorControlChain {
|
||||
*/
|
||||
public function setSuppression($suppression) {
|
||||
$this->suppression = (bool)$suppression;
|
||||
// Don't modify errors unless handling fatal errors, and if errors were
|
||||
// originally allowed to be displayed.
|
||||
if ($this->handleFatalErrors && $this->originalDisplayErrors) {
|
||||
ini_set('display_errors', !$suppression);
|
||||
// If handling fatal errors, conditionally disable, or restore error display
|
||||
// Note: original value of display_errors could also evaluate to "off"
|
||||
if ($this->handleFatalErrors) {
|
||||
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
|
||||
* that $error must be in this point in the chain for the callback to be called
|
||||
@ -178,7 +200,7 @@ class ErrorControlChain {
|
||||
register_shutdown_function(array($this, 'handleFatalError'));
|
||||
$this->handleFatalErrors = true;
|
||||
|
||||
$this->originalDisplayErrors = ini_get('display_errors');
|
||||
$this->originalDisplayErrors = $this->getDisplayErrors();
|
||||
$this->setSuppression($this->suppression);
|
||||
|
||||
$this->step();
|
||||
@ -202,7 +224,7 @@ class ErrorControlChain {
|
||||
else {
|
||||
// Now clean up
|
||||
$this->handleFatalErrors = false;
|
||||
ini_set('display_errors', $this->originalDisplayErrors);
|
||||
$this->setDisplayErrors($this->originalDisplayErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ class GridFieldExportButton implements GridField_HTMLProvider, GridField_ActionP
|
||||
} else {
|
||||
$value = $gridField->getDataFieldValue($item, $columnSource);
|
||||
|
||||
if(!$value) {
|
||||
if($value === null) {
|
||||
$value = $gridField->getDataFieldValue($item, $columnHeader);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
*/
|
||||
class DBLocale extends Varchar {
|
||||
|
||||
public function __construct($name, $size = 16) {
|
||||
public function __construct($name = null, $size = 16) {
|
||||
parent::__construct($name, $size);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,30 @@
|
||||
*/
|
||||
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
|
||||
public function translateMemstring($memstring) {
|
||||
return parent::translateMemstring($memstring);
|
||||
@ -63,10 +87,7 @@ require_once '$classpath';
|
||||
|
||||
class ErrorControlChainTest extends SapphireTest {
|
||||
|
||||
protected $displayErrors = null;
|
||||
|
||||
function setUp() {
|
||||
$this->displayErrors = (bool)ini_get('display_errors');
|
||||
|
||||
// Check we can run PHP at all
|
||||
$null = is_writeable('/dev/null') ? '/dev/null' : 'NUL';
|
||||
@ -80,50 +101,55 @@ class ErrorControlChainTest extends SapphireTest {
|
||||
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() {
|
||||
|
||||
// Errors disabled by default
|
||||
ini_set('display_errors', false);
|
||||
$chain = new ErrorControlChain();
|
||||
$chain = new ErrorControlChainTest_Chain();
|
||||
$chain->setDisplayErrors('Off'); // mocks display_errors: Off
|
||||
$initialValue = null;
|
||||
$whenNotSuppressed = null;
|
||||
$whenSuppressed = null;
|
||||
$chain->then(function($chain) use(&$whenNotSuppressed, &$whenSuppressed) {
|
||||
$chain->setSuppression(true);
|
||||
$whenSuppressed = ini_get('display_errors');
|
||||
$chain->setSuppression(false);
|
||||
$whenNotSuppressed = ini_get('display_errors');
|
||||
})->execute();
|
||||
$chain->then(
|
||||
function(ErrorControlChainTest_Chain $chain)
|
||||
use(&$initialValue, &$whenNotSuppressed, &$whenSuppressed) {
|
||||
$initialValue = $chain->getDisplayErrors();
|
||||
$chain->setSuppression(false);
|
||||
$whenNotSuppressed = $chain->getDisplayErrors();
|
||||
$chain->setSuppression(true);
|
||||
$whenSuppressed = $chain->getDisplayErrors();
|
||||
}
|
||||
)->execute();
|
||||
|
||||
// Disabled errors never un-disable
|
||||
$this->assertFalse((bool)$whenNotSuppressed);
|
||||
$this->assertFalse((bool)$whenSuppressed);
|
||||
$this->assertEquals(0, $initialValue); // Chain starts suppressed
|
||||
$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
|
||||
ini_set('display_errors', true);
|
||||
$chain = new ErrorControlChain();
|
||||
$chain = new ErrorControlChainTest_Chain();
|
||||
$chain->setDisplayErrors('Yes'); // non-falsey ini value
|
||||
$initialValue = null;
|
||||
$whenNotSuppressed = null;
|
||||
$whenSuppressed = null;
|
||||
$chain->then(function($chain) use(&$whenNotSuppressed, &$whenSuppressed) {
|
||||
$chain->setSuppression(true);
|
||||
$whenSuppressed = ini_get('display_errors');
|
||||
$chain->setSuppression(false);
|
||||
$whenNotSuppressed = ini_get('display_errors');
|
||||
})->execute();
|
||||
$chain->then(
|
||||
function(ErrorControlChainTest_Chain $chain)
|
||||
use(&$initialValue, &$whenNotSuppressed, &$whenSuppressed) {
|
||||
$initialValue = $chain->getDisplayErrors();
|
||||
$chain->setSuppression(true);
|
||||
$whenSuppressed = $chain->getDisplayErrors();
|
||||
$chain->setSuppression(false);
|
||||
$whenNotSuppressed = $chain->getDisplayErrors();
|
||||
}
|
||||
)->execute();
|
||||
|
||||
// Errors can be suppressed an un-suppressed when initially enabled
|
||||
$this->assertTrue((bool)$whenNotSuppressed);
|
||||
$this->assertFalse((bool)$whenSuppressed);
|
||||
$this->assertEquals(0, $initialValue); // Chain starts suppressed
|
||||
$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
|
||||
|
||||
$chain = new ErrorControlChainTest_Chain();
|
||||
|
||||
list($out, $code) = $chain
|
||||
|
@ -115,6 +115,18 @@ class GridFieldExportButtonTest extends SapphireTest {
|
||||
$button->generateExportFileData($this->gridField)
|
||||
);
|
||||
}
|
||||
|
||||
public function testZeroValue() {
|
||||
$button = new GridFieldExportButton();
|
||||
$button->setExportColumns(array(
|
||||
'RugbyTeamNumber' => 'Rugby Team Number'
|
||||
));
|
||||
|
||||
$this->assertEquals(
|
||||
"\"Rugby Team Number\"\n\"2\"\n\"0\"\n",
|
||||
$button->generateExportFileData($this->gridField)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,7 +137,8 @@ class GridFieldExportButtonTest_Team extends DataObject implements TestOnly {
|
||||
|
||||
private static $db = array(
|
||||
'Name' => 'Varchar',
|
||||
'City' => 'Varchar'
|
||||
'City' => 'Varchar',
|
||||
'RugbyTeamNumber' => 'Int'
|
||||
);
|
||||
|
||||
public function canView($member = null) {
|
||||
@ -142,7 +155,8 @@ class GridFieldExportButtonTest_NoView extends DataObject implements TestOnly {
|
||||
|
||||
private static $db = array(
|
||||
'Name' => 'Varchar',
|
||||
'City' => 'Varchar'
|
||||
'City' => 'Varchar',
|
||||
'RugbyTeamNumber' => 'Int'
|
||||
);
|
||||
|
||||
public function canView($member = null) {
|
||||
|
@ -2,9 +2,11 @@ GridFieldExportButtonTest_Team:
|
||||
test-team-1:
|
||||
Name: Test
|
||||
City: City
|
||||
RugbyTeamNumber: 2
|
||||
test-team-2:
|
||||
Name: Test2
|
||||
City: City2
|
||||
RugbyTeamNumber: 0
|
||||
|
||||
GridFieldExportButtonTest_NoView:
|
||||
item1:
|
||||
|
Loading…
Reference in New Issue
Block a user