mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge branch '3.7' into 3
This commit is contained in:
commit
6a6eaf30f3
0
core/compat/_manifest_exclude
Normal file
0
core/compat/_manifest_exclude
Normal file
21
docs/en/04_Changelogs/3.6.7.md
Normal file
21
docs/en/04_Changelogs/3.6.7.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# 3.6.7
|
||||||
|
|
||||||
|
<!--- Changes below this line will be automatically regenerated -->
|
||||||
|
|
||||||
|
## Change Log
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
* 2019-01-10 [c44f06cdf](https://github.com/silverstripe/silverstripe-framework/commit/c44f06cdf10387a987e4efb096ff06b3bb4495ef) Patch SQL Injection vulnerability when arrays are assigned to DataObject Fields (Aaron Carlino) - See [ss-2018-021](https://www.silverstripe.org/download/security-releases/ss-2018-021)
|
||||||
|
* 2018-09-26 [598edd913](https://github.com/silverstripe/silverstripe-framework/commit/598edd91341f389d7b919ec1201e03d2aba4d284) Add confirmation token to dev/build (Loz Calver) - See [ss-2018-019](https://www.silverstripe.org/download/security-releases/ss-2018-019)
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
* 2019-01-23 [746c0679a](https://github.com/silverstripe/silverstripe-framework/commit/746c0679ad1d6ceac03d2adf167367f0ca2259cd) Injector may instantiate prototypes as if they're singletons (fixes #8567) (Loz Calver)
|
||||||
|
* 2018-11-15 [86701b8cd](https://github.com/silverstripe/silverstripe-framework/commit/86701b8cd0cd5f8de813a7c9347e7c8055d878f4) Redirect loop with multiple URL tokens (fixes #8607) (Loz Calver)
|
||||||
|
* 2018-06-04 [41e601a03](https://github.com/silverstripe/silverstripe-framework/commit/41e601a036307065d9ea2ba8862f67be738d402f) Regression from #8009 (Daniel Hensby)
|
||||||
|
* 2018-05-29 [1cbf27e0f](https://github.com/silverstripe/silverstripe-framework/commit/1cbf27e0f47c3547914b03193d0f5f77c87ff8d5) PHP 5.3 compat for referencing $this in closure, and make method public for same reason (Robbie Averill)
|
||||||
|
* 2018-04-17 [af3a9f3ec](https://github.com/silverstripe/silverstripe-framework/commit/af3a9f3ec8a5465f841c5aa8ee1faf40c1b76bf4) Duplicating many_many relationships looses the extra fields (fixes #7973) (UndefinedOffset)
|
||||||
|
* 2018-03-15 [d17d93f7](https://github.com/silverstripe/silverstripe-cms/commit/d17d93f784a6e01f3d396c55adc623d69a90261a) Remove SearchForm results() function from allowed_actions (Steve Dixon)
|
||||||
|
* 2018-02-16 [86addea1d](https://github.com/silverstripe/silverstripe-framework/commit/86addea1d2a7b2e28ae8115279ae358bcb46648a) Split HTML manipulation to onadd, so elements are not accidentally duplicated (Christopher Joe)
|
||||||
|
* 2018-02-13 [c767e472d](https://github.com/silverstripe/silverstripe-framework/commit/c767e472dc494408460ef47c27b8d34475da4ac6) DataObject singleton creation (Jonathon Menz)
|
16
docs/en/04_Changelogs/3.7.3.md
Normal file
16
docs/en/04_Changelogs/3.7.3.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# 3.7.3
|
||||||
|
|
||||||
|
<!--- Changes below this line will be automatically regenerated -->
|
||||||
|
|
||||||
|
## Change Log
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
* 2019-01-10 [6bf9542d6](https://github.com/silverstripe/silverstripe-framework/commit/6bf9542d664ac7935691c8055505b7ad8ea26e9a) Patch SQL Injection vulnerability when arrays are assigned to DataObject Fields (Maxime Rainville) - See [ss-2018-021](https://www.silverstripe.org/download/security-releases/ss-2018-021)
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
* 2019-01-30 [8e6e70335](https://github.com/silverstripe/silverstripe-framework/commit/8e6e70335895063c6e6cfd99cfcfb50c6f9c2ad9) Block Manifest of the compatibility class Object and lean on model/fieldtypes/compat/autoload.php (UndefinedOffset)
|
||||||
|
* 2019-01-23 [746c0679a](https://github.com/silverstripe/silverstripe-framework/commit/746c0679ad1d6ceac03d2adf167367f0ca2259cd) Injector may instantiate prototypes as if they're singletons (fixes #8567) (Loz Calver)
|
||||||
|
* 2019-01-11 [16a837d6a](https://github.com/silverstripe/silverstripe-framework/commit/16a837d6a093115755cd821c63be1e3be088645b) fix [Warning] on count() with PHP >= 7.2 (lerni)
|
||||||
|
* 2018-11-15 [86701b8cd](https://github.com/silverstripe/silverstripe-framework/commit/86701b8cd0cd5f8de813a7c9347e7c8055d878f4) Redirect loop with multiple URL tokens (fixes #8607) (Loz Calver)
|
@ -1357,6 +1357,21 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
|||||||
$manipulation[$baseTable]['command'] = 'update';
|
$manipulation[$baseTable]['command'] = 'update';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure none of our field assignment are arrays
|
||||||
|
foreach ($manipulation as $tableManipulation) {
|
||||||
|
if (!isset($tableManipulation['fields'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach ($tableManipulation['fields'] as $fieldValue) {
|
||||||
|
if (is_array($fieldValue)) {
|
||||||
|
user_error(
|
||||||
|
'DataObject::writeManipulation: parameterised field assignments are disallowed',
|
||||||
|
E_USER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Perform the manipulation
|
// Perform the manipulation
|
||||||
DB::manipulate($manipulation);
|
DB::manipulate($manipulation);
|
||||||
}
|
}
|
||||||
@ -2663,6 +2678,18 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
|||||||
user_error('DataObject::setField: passed an object that is not a DBField', E_USER_WARNING);
|
user_error('DataObject::setField: passed an object that is not a DBField', E_USER_WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$dbField = $this->dbObject($fieldName);
|
||||||
|
if ($dbField && $dbField->scalarValueOnly() && !empty($val) && !is_scalar($val)){
|
||||||
|
$val = null;
|
||||||
|
user_error(
|
||||||
|
sprintf(
|
||||||
|
'DataObject::setField: %s only accepts scalars',
|
||||||
|
$fieldName
|
||||||
|
),
|
||||||
|
E_USER_WARNING
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// if a field is not existing or has strictly changed
|
// if a field is not existing or has strictly changed
|
||||||
if(!isset($this->record[$fieldName]) || $this->record[$fieldName] !== $val) {
|
if(!isset($this->record[$fieldName]) || $this->record[$fieldName] !== $val) {
|
||||||
// TODO Add check for php-level defaults which are not set in the db
|
// TODO Add check for php-level defaults which are not set in the db
|
||||||
|
@ -270,6 +270,21 @@ class ManyManyList extends RelationList {
|
|||||||
$manipulation[$this->joinTable]['fields'][$this->localKey] = $itemID;
|
$manipulation[$this->joinTable]['fields'][$this->localKey] = $itemID;
|
||||||
$manipulation[$this->joinTable]['fields'][$this->foreignKey] = $foreignID;
|
$manipulation[$this->joinTable]['fields'][$this->foreignKey] = $foreignID;
|
||||||
|
|
||||||
|
// Make sure none of our field assignment are arrays
|
||||||
|
foreach ($manipulation as $tableManipulation) {
|
||||||
|
if (!isset($tableManipulation['fields'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach ($tableManipulation['fields'] as $fieldValue) {
|
||||||
|
if (is_array($fieldValue)) {
|
||||||
|
user_error(
|
||||||
|
'ManyManyList::add: parameterised field assignments are disallowed',
|
||||||
|
E_USER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DB::manipulate($manipulation);
|
DB::manipulate($manipulation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ abstract class DBField extends ViewableData {
|
|||||||
* @return mixed The raw value, or escaped parameterised details
|
* @return mixed The raw value, or escaped parameterised details
|
||||||
*/
|
*/
|
||||||
public function prepValueForDB($value) {
|
public function prepValueForDB($value) {
|
||||||
if($value === null || $value === "" || $value === false) {
|
if($value === null || $value === "" || $value === false || ($this->scalarValueOnly() && !is_scalar($value))) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return $value;
|
return $value;
|
||||||
@ -351,4 +351,15 @@ DBG;
|
|||||||
public function __toString() {
|
public function __toString() {
|
||||||
return $this->forTemplate();
|
return $this->forTemplate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whatever this DBField only accepts scalar values.
|
||||||
|
*
|
||||||
|
* Composite DBField to override this method and return `false`. So they can accept arrays of values.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function scalarValueOnly()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,4 +306,10 @@ class Money extends DBField implements CompositeDBField {
|
|||||||
public function __toString() {
|
public function __toString() {
|
||||||
return (string)$this->getAmount();
|
return (string)$this->getAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function scalarValueOnly()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -190,4 +190,9 @@ class PolymorphicForeignKey extends ForeignKey implements CompositeDBField {
|
|||||||
public function exists() {
|
public function exists() {
|
||||||
return $this->getClassValue() && $this->getIDValue();
|
return $this->getClassValue() && $this->getIDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function scalarValueOnly()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,6 +167,53 @@ class DBFieldTest extends SapphireTest {
|
|||||||
$this->assertEquals(PHP_INT_MAX, $bigInt->getValue());
|
$this->assertEquals(PHP_INT_MAX, $bigInt->getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataProviderPrepValueForDBArrayValue
|
||||||
|
*/
|
||||||
|
public function testPrepValueForDBArrayValue($dbFieldName, $scalarValueOnly, $extraArgs = array())
|
||||||
|
{
|
||||||
|
$reflection = new ReflectionClass($dbFieldName);
|
||||||
|
/** @var DBField $dbField */
|
||||||
|
$dbField = $reflection->newInstanceArgs($extraArgs);
|
||||||
|
$dbField->setName('SomeField');
|
||||||
|
$payload = array('GREATEST(0,?)' => '2');
|
||||||
|
$preparedValue = $dbField->prepValueForDB($payload);
|
||||||
|
$this->assertTrue(
|
||||||
|
!$scalarValueOnly || !is_array($preparedValue),
|
||||||
|
'`prepValueForDB` can not return an array if scalarValueOnly is true'
|
||||||
|
);
|
||||||
|
$this->assertEquals($scalarValueOnly, $dbField->scalarValueOnly());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataProviderPrepValueForDBArrayValue()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('BigInt', true),
|
||||||
|
array('Boolean', true),
|
||||||
|
array('Currency', true),
|
||||||
|
array('Date', true),
|
||||||
|
array('SS_Datetime', true),
|
||||||
|
array('DBLocale', true),
|
||||||
|
array('Decimal', true),
|
||||||
|
array('Double', true),
|
||||||
|
array('Enum', true),
|
||||||
|
array('Float', true),
|
||||||
|
array('ForeignKey', true, array('SomeField')),
|
||||||
|
array('HTMLText', true),
|
||||||
|
array('HTMLVarchar', true),
|
||||||
|
array('Int', true),
|
||||||
|
array('Money', false),
|
||||||
|
array('MultiEnum', true, array('SomeField', array('One', 'Two', 'Three'))),
|
||||||
|
array('Percentage', true),
|
||||||
|
array('PolymorphicForeignKey', false, array('SomeField')),
|
||||||
|
array('PrimaryKey', true, array('SomeField', singleton('Image'))),
|
||||||
|
array('Text', true),
|
||||||
|
array('Time', true),
|
||||||
|
array('Varchar', true),
|
||||||
|
array('Year', true),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testExists() {
|
public function testExists() {
|
||||||
$varcharField = new Varchar("testfield");
|
$varcharField = new Varchar("testfield");
|
||||||
$this->assertTrue($varcharField->getNullifyEmpty());
|
$this->assertTrue($varcharField->getNullifyEmpty());
|
||||||
|
@ -1754,6 +1754,25 @@ class DataObjectTest extends SapphireTest {
|
|||||||
$this->assertEquals(PHP_INT_MAX, DataObjectTest_Staff::get()->byID($staff->ID)->Salary);
|
$this->assertEquals(PHP_INT_MAX, DataObjectTest_Staff::get()->byID($staff->ID)->Salary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException PHPUnit_Framework_Error_Warning
|
||||||
|
*/
|
||||||
|
public function testSetFieldWithArrayOnScalarOnlyField()
|
||||||
|
{
|
||||||
|
$do = singleton('DataObjectTest_CompositeDBField');
|
||||||
|
$do->NonCompositeField = 'Some Value';
|
||||||
|
$do->NonCompositeField = array('Amount' => 123, 'Currency' => 'CAD');
|
||||||
|
$this->assertEmpty($do->NonCompositeField);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetFieldWithArrayOnCompositeField()
|
||||||
|
{
|
||||||
|
$do = singleton('DataObjectTest_CompositeDBField');
|
||||||
|
$do->CompositeMoneyField = array('Amount' => 123, 'Currency' => 'CAD');
|
||||||
|
$this->assertNotEmpty($do->CompositeMoneyField);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DataObjectTest_Sortable extends DataObject implements TestOnly {
|
class DataObjectTest_Sortable extends DataObject implements TestOnly {
|
||||||
@ -2035,3 +2054,9 @@ class DataObjectTest_Bogey extends DataObject implements TestOnly {}
|
|||||||
|
|
||||||
DataObjectTest_Team::add_extension('DataObjectTest_Team_Extension');
|
DataObjectTest_Team::add_extension('DataObjectTest_Team_Extension');
|
||||||
|
|
||||||
|
class DataObjectTest_CompositeDBField extends DataObject implements TestOnly {
|
||||||
|
private static $db = array(
|
||||||
|
'NonCompositeField' => 'Varchar',
|
||||||
|
'CompositeMoneyField' => 'Money',
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user