Merge branch '3.4' into 3

This commit is contained in:
Daniel Hensby 2016-10-16 22:56:37 +01:00
commit 9a6121c867
No known key found for this signature in database
GPG Key ID: B00D1E9767F0B06E
12 changed files with 230 additions and 71 deletions

View File

@ -359,6 +359,15 @@ class Session {
$path = Config::inst()->get('Session', 'cookie_path');
if(!$path) $path = Director::baseURL();
$domain = Config::inst()->get('Session', 'cookie_domain');
// Director::baseURL can return absolute domain names - this extracts the relevant parts
// for the session otherwise we can get broken session cookies
if (Director::is_absolute_url($path)) {
$urlParts = parse_url($path);
$path = $urlParts['path'];
if (!$domain) {
$domain = $urlParts['host'];
}
}
$secure = Director::is_https() && Config::inst()->get('Session', 'cookie_secure');
$session_path = Config::inst()->get('Session', 'session_store_path');
$timeout = Config::inst()->get('Session', 'timeout');

View File

@ -777,7 +777,7 @@ abstract class Object {
} else {
// Please do not change the exception code number below.
$class = get_class($this);
throw new Exception("Object->__call(): the method '$method' does not exist on '$class'", 2175);
throw new Exception("Object->__call(): the method '$method' does not exist on '$class', or the method is not public.", 2175);
}
}

View File

@ -333,21 +333,22 @@ class CheckboxSetField extends OptionsetField {
return true;
}
$sourceArray = $this->getSourceAsArray();
$validValues = array_keys($sourceArray);
if (is_array($values)) {
if (!array_intersect_key($sourceArray, $values)) {
if (!array_intersect($validValues, $values)) {
$validator->validationError(
$this->name,
_t(
'CheckboxSetField.SOURCE_VALIDATION',
"Please select a value within the list provided. '{value}' is not a valid option",
array('value' => implode(' and ', array_diff($sourceArray, $values)))
array('value' => implode(' and ', $values))
),
"validation"
);
return false;
}
} else {
if (!in_array($this->value, $sourceArray)) {
if (!in_array($this->value, $validValues)) {
$validator->validationError(
$this->name,
_t(

View File

@ -318,13 +318,22 @@ class DropdownField extends FormField {
public function getSourceAsArray()
{
$source = $this->getSource();
// Simplify source if presented as dataobject list
if ($source instanceof SS_List) {
$source = $source->map();
}
if ($source instanceof SS_Map) {
$source = $source->toArray();
}
if (is_array($source)) {
return $source;
} else {
$sourceArray = array();
foreach ($source as $key => $value) {
$sourceArray[$key] = $value;
}
}
$sourceArray = array();
foreach ($source as $key => $value) {
$sourceArray[$key] = $value;
}
return $sourceArray;
}

View File

@ -550,7 +550,12 @@ class FieldList extends ArrayList {
public function makeFieldReadonly($field) {
$fieldName = ($field instanceof FormField) ? $field->getName() : $field;
$srcField = $this->dataFieldByName($fieldName);
$this->replaceField($fieldName, $srcField->performReadonlyTransformation());
if($srcField) {
$this->replaceField($fieldName, $srcField->performReadonlyTransformation());
}
else {
user_error("Trying to make field '$fieldName' readonly, but it does not exist in the list",E_USER_WARNING);
}
}
/**

View File

@ -448,7 +448,7 @@ class ArrayList extends ViewableData implements SS_List, SS_Filterable, SS_Sorta
// First argument is the direction to be sorted,
$multisortArgs[] = &$sortDirection[$column];
if ($firstRun) {
$multisortArgs[] = defined('SORT_NATURAL') ? SORT_NATURAL : SORT_STRING;
$multisortArgs[] = SORT_REGULAR;
}
$firstRun = false;
}

View File

@ -177,28 +177,65 @@ class CheckboxSetFieldTest extends SapphireTest {
$tag1 = $this->objFromFixture('CheckboxSetFieldTest_Tag', 'tag1');
$tag2 = $this->objFromFixture('CheckboxSetFieldTest_Tag', 'tag2');
$tag3 = $this->objFromFixture('CheckboxSetFieldTest_Tag', 'tag3');
$field = CheckboxSetField::create('Test', 'Testing', $checkboxTestArticle->Tags() ->map());
$field = CheckboxSetField::create('Test', 'Testing', $checkboxTestArticle->Tags());
$validator = new RequiredFields();
$field->setValue(array(
$tag1->ID => $tag1->ID,
$tag2->ID => $tag2->ID
));
$field->setValue(array( $tag1->ID, $tag2->ID ));
$isValid = $field->validate($validator);
$this->assertTrue(
$field->validate($validator),
$isValid,
'Validates values in source map'
);
//invalid value should fail
// Invalid value should fail
$validator = new RequiredFields();
$fakeID = CheckboxSetFieldTest_Tag::get()->max('ID') + 1;
$field->setValue(array($fakeID => $fakeID));
$field->setValue(array($fakeID));
$this->assertFalse(
$field->validate($validator),
'Field does not valid values outside of source map'
);
//non valid value included with valid options should succeed
$errors = $validator->getErrors();
$error = reset($errors);
$this->assertEquals(
"Please select a value within the list provided. '$fakeID' is not a valid option",
$error['message']
);
// Multiple invalid values should fail
$validator = new RequiredFields();
$fakeID = CheckboxSetFieldTest_Tag::get()->max('ID') + 1;
$field->setValue(array($fakeID, $tag3->ID));
$this->assertFalse(
$field->validate($validator),
'Field does not valid values outside of source map'
);
$errors = $validator->getErrors();
$error = reset($errors);
$this->assertEquals(
"Please select a value within the list provided. '{$fakeID} and {$tag3->ID}' is not a valid option",
$error['message']
);
// Invalid value with non-array value
$validator = new RequiredFields();
$field->setValue($fakeID);
$this->assertFalse(
$field->validate($validator),
'Field does not valid values outside of source map'
);
$errors = $validator->getErrors();
$error = reset($errors);
$this->assertEquals(
"Please select a value within the list provided. '{$fakeID}' is not a valid option",
$error['message']
);
// non valid value included with valid options should succeed
$validator = new RequiredFields();
$field->setValue(array(
$tag1->ID => $tag1->ID,
$tag2->ID => $tag2->ID,
$tag3->ID => $tag3->ID
$tag1->ID,
$tag2->ID,
$tag3->ID
));
$this->assertTrue(
$field->validate($validator),

View File

@ -6,12 +6,37 @@
class DropdownFieldTest extends SapphireTest {
public function testGetSource() {
$source = array(1=>'one');
$source = array(1=>'one', 2 => 'two');
$field = new DropdownField('Field', null, $source);
$this->assertEquals(
$field->getSource(),
$source,
$field->getSource()
);
$this->assertEquals(
$source,
$field->getSourceAsArray()
);
$items = new ArrayList(array(
array( 'ID' => 1, 'Title' => 'ichi', 'OtherField' => 'notone' ),
array( 'ID' => 2, 'Title' => 'ni', 'OtherField' => 'nottwo' ),
));
$field->setSource($items);
$this->assertEquals(
$field->getSourceAsArray(),
array(
1 => 'one'
1 => 'ichi',
2 => 'ni',
)
);
$map = new SS_Map($items, 'ID', 'OtherField');
$field->setSource($map);
$this->assertEquals(
$field->getSourceAsArray(),
array(
1 => 'notone',
2 => 'nottwo',
)
);
}

View File

@ -314,67 +314,46 @@ class ArrayListTest extends SapphireTest {
), $list->toArray());
}
public function testNaturalSort() {
//natural sort is only available in 5.4+
if (version_compare(phpversion(), '5.4.0', '<')) {
$this->markTestSkipped();
}
$list = new ArrayList(array(
array('Name' => 'Steve'),
public function testMixedCaseSort() {
// Note: Natural sorting is not expected, so if 'bonny10' were included
// below we would expect it to appear between bonny1 and bonny2. That's
// undesirable though so we're not enforcing it in tests.
$original = array(
array('Name' => 'Steve'),
(object) array('Name' => 'Bob'),
array('Name' => 'John'),
array('Name' => 'bonny'),
array('Name' => 'bonny1'),
array('Name' => 'bonny10'),
//array('Name' => 'bonny10'),
array('Name' => 'bonny2'),
));
);
$list = new ArrayList($original);
$expected = array(
(object) array('Name' => 'Bob'),
array('Name' => 'bonny'),
array('Name' => 'bonny1'),
//array('Name' => 'bonny10'),
array('Name' => 'bonny2'),
array('Name' => 'John'),
array('Name' => 'Steve'),
);
// Unquoted name
$list1 = $list->sort('Name');
$this->assertEquals(array(
(object) array('Name' => 'Bob'),
array('Name' => 'bonny'),
array('Name' => 'bonny1'),
array('Name' => 'bonny2'),
array('Name' => 'bonny10'),
array('Name' => 'John'),
array('Name' => 'Steve'),
), $list1->toArray());
$this->assertEquals($expected, $list1->toArray());
// Quoted name name
$list2 = $list->sort('"Name"');
$this->assertEquals(array(
(object) array('Name' => 'Bob'),
array('Name' => 'bonny'),
array('Name' => 'bonny1'),
array('Name' => 'bonny2'),
array('Name' => 'bonny10'),
array('Name' => 'John'),
array('Name' => 'Steve'),
), $list2->toArray());
$this->assertEquals($expected, $list2->toArray());
// Array (non-associative)
$list3 = $list->sort(array('"Name"'));
$this->assertEquals(array(
(object) array('Name' => 'Bob'),
array('Name' => 'bonny'),
array('Name' => 'bonny1'),
array('Name' => 'bonny2'),
array('Name' => 'bonny10'),
array('Name' => 'John'),
array('Name' => 'Steve'),
), $list3->toArray());
$this->assertEquals($expected, $list3->toArray());
// Check original list isn't altered
$this->assertEquals(array(
array('Name' => 'Steve'),
(object) array('Name' => 'Bob'),
array('Name' => 'John'),
array('Name' => 'bonny'),
array('Name' => 'bonny1'),
array('Name' => 'bonny10'),
array('Name' => 'bonny2'),
), $list->toArray());
$this->assertEquals($original, $list->toArray());
}
@ -472,6 +451,42 @@ class ArrayListTest extends SapphireTest {
));
}
public function testSortNumeric() {
$list = new ArrayList(array(
array('Sort' => 0),
array('Sort' => -1),
array('Sort' => 1),
array('Sort' => -2),
array('Sort' => 2),
array('Sort' => -10),
array('Sort' => 10)
));
// Sort descending
$list1 = $list->sort('Sort', 'DESC');
$this->assertEquals(array(
array('Sort' => 10),
array('Sort' => 2),
array('Sort' => 1),
array('Sort' => 0),
array('Sort' => -1),
array('Sort' => -2),
array('Sort' => -10)
), $list1->toArray());
// Sort ascending
$list1 = $list->sort('Sort', 'ASC');
$this->assertEquals(array(
array('Sort' => -10),
array('Sort' => -2),
array('Sort' => -1),
array('Sort' => 0),
array('Sort' => 1),
array('Sort' => 2),
array('Sort' => 10)
), $list1->toArray());
}
public function testReverse() {
$list = new ArrayList(array(
array('Name' => 'John'),

View File

@ -23,6 +23,7 @@ class DataListTest extends SapphireTest {
'DataObjectTest_EquipmentCompany',
'DataObjectTest_SubEquipmentCompany',
'DataObjectTest\NamespacedClass',
'DataObjectTest_Sortable',
'DataObjectTest_Company',
'DataObjectTest_Fan',
'ManyManyListTest_Product',
@ -533,6 +534,34 @@ class DataListTest extends SapphireTest {
$this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil');
}
public function testSortNumeric() {
$list = DataObjectTest_Sortable::get();
$list1 = $list->sort('Sort', 'ASC');
$this->assertEquals(array(
-10,
-2,
-1,
0,
1,
2,
10
), $list1->column('Sort'));
}
public function testSortMixedCase() {
$list = DataObjectTest_Sortable::get();
$list1 = $list->sort('Name', 'ASC');
$this->assertEquals(array(
'Bob',
'bonny',
'jane',
'John',
'sam',
'Steve',
'steven'
), $list1->column('Name'));
}
/**
* Test DataList->canFilterBy()
*/

View File

@ -1709,6 +1709,13 @@ class DataObjectTest extends SapphireTest {
}
class DataObjectTest_Sortable extends DataObject implements TestOnly {
private static $db = array(
'Sort' => 'Int',
'Name' => 'Varchar',
);
}
class DataObjectTest_Player extends Member implements TestOnly {
private static $db = array(
'IsRetired' => 'Boolean',

View File

@ -1,3 +1,25 @@
DataObjectTest_Sortable:
numeric1:
Sort: 0
Name: steven
numeric2:
Sort: -1
Name: bonny
numeric3:
Sort: 1
Name: sam
numeric4:
Sort: -2
Name: Bob
numeric5:
Sort: 2
Name: jane
numeric6:
Sort: -10
Name: Steve
numeric7:
Sort: 10
Name: John
DataObjectTest_EquipmentCompany:
equipmentcompany1:
Name: Company corp