To run SilverStripe, please install PHP 5.0 or greater.
+
+
We have detected that you are running PHP version $PHPVersion. In order to run SilverStripe,
+ you must have PHP version 5.0 or greater, and for best results we recommend PHP 5.2 or greater.
+
+
If you are running on a shared host, you may need to ask your hosting provider how to do this.
You can use this to keep track of work that needs to be done to the content of your site. To see all your pages with to do information, open the \'Site Reports\' window on the left and select \'To Do\'
';
$lang['en_US']['SiteTree']['TOPLEVEL'] = 'Site Content (Top Level)';
diff --git a/main.php b/main.php
index 2234cc22a..88545c462 100644
--- a/main.php
+++ b/main.php
@@ -1,5 +1,21 @@
RelativeLink();
-
- $fields->push(new HiddenField('formController', null, $formController));
- $fields->push(new HiddenField('executeForm', null, $name));
-
parent::__construct($controller, $name, $fields, $actions);
+ $this->setFormMethod('get');
+
$this->disableSecurityToken();
}
- function FormMethod() {
- return "get";
- }
-
- public function forTemplate(){
+ public function forTemplate() {
return $this->renderWith(array(
'SearchForm',
'Form'
@@ -74,11 +68,11 @@ class SearchForm extends Form {
* Return dataObjectSet of the results using $_REQUEST to get info from form.
* Wraps around {@link searchEngine()}.
*
- * @param int $numPerPage DEPRECATED 2.3 Use SearchForm->numPerPage
+ * @param int $pageLength DEPRECATED 2.3 Use SearchForm->pageLength
* @param array $data Request data as an associative array. Should contain at least a key 'Search' with all searched keywords.
* @return DataObjectSet
*/
- public function getResults($numPerPage = null, $data = null){
+ public function getResults($pageLength = null, $data = null){
// legacy usage: $data was defaulting to $_REQUEST, parameter not passed in doc.silverstripe.com tutorials
if(!isset($data)) $data = $_REQUEST;
@@ -99,9 +93,9 @@ class SearchForm extends Form {
$keywords = $this->addStarsToKeywords($keywords);
if(strpos($keywords, '"') !== false || strpos($keywords, '+') !== false || strpos($keywords, '-') !== false || strpos($keywords, '*') !== false) {
- $results = $this->searchEngine($keywords, $numPerPage, "Relevance DESC", "", true);
+ $results = $this->searchEngine($keywords, $pageLength, "Relevance DESC", "", true);
} else {
- $results = $this->searchEngine($keywords, $numPerPage);
+ $results = $this->searchEngine($keywords, $pageLength);
}
// filter by permission
@@ -139,8 +133,8 @@ class SearchForm extends Form {
*
* @param string $keywords Keywords as a string.
*/
- public function searchEngine($keywords, $numPerPage = null, $sortBy = "Relevance DESC", $extraFilter = "", $booleanSearch = false, $alternativeFileFilter = "", $invertedMatch = false) {
- if(!$numPerPage) $numPerPage = $this->numPerPage;
+ public function searchEngine($keywords, $pageLength = null, $sortBy = "Relevance DESC", $extraFilter = "", $booleanSearch = false, $alternativeFileFilter = "", $invertedMatch = false) {
+ if(!$pageLength) $pageLength = $this->pageLength;
$fileFilter = '';
$keywords = addslashes($keywords);
@@ -155,7 +149,7 @@ class SearchForm extends Form {
if($this->showInSearchTurnOn) $extraFilter .= " AND showInSearch <> 0";
$start = isset($_GET['start']) ? (int)$_GET['start'] : 0;
- $limit = $start . ", " . (int) $numPerPage;
+ $limit = $start . ", " . (int) $pageLength;
$notMatch = $invertedMatch ? "NOT " : "";
if($keywords) {
@@ -201,7 +195,7 @@ class SearchForm extends Form {
if(isset($objects)) $doSet = new DataObjectSet($objects);
else $doSet = new DataObjectSet();
- $doSet->setPageLimits($start, $numPerPage, $totalCount);
+ $doSet->setPageLimits($start, $pageLength, $totalCount);
return $doSet;
}
@@ -217,6 +211,23 @@ class SearchForm extends Form {
return Convert::raw2xml($data['Search']);
}
+
+ /**
+ * Set the maximum number of records shown on each page.
+ *
+ * @param int $length
+ */
+ public function setPageLength($length) {
+ $this->pageLength = $length;
+ }
+
+ /**
+ * @return int
+ */
+ public function getPageLength() {
+ // legacy handling for deprecated $numPerPage
+ return (isset($this->numPerPage)) ? $this->numPerPage : $this->pageLength;
+ }
}
diff --git a/search/filters/SearchFilter.php b/search/filters/SearchFilter.php
index 2e92dabe3..7853383c1 100644
--- a/search/filters/SearchFilter.php
+++ b/search/filters/SearchFilter.php
@@ -82,6 +82,9 @@ abstract class SearchFilter extends Object {
* @return string
*/
function getDbName() {
+ // Special handler for "NULL" relations
+ if($this->name == "NULL") return $this->name;
+
// SRM: This code finds the table where the field named $this->name lives
// Todo: move to somewhere more appropriate, such as DataMapper, the magical class-to-be?
$candidateClass = $this->model;
@@ -140,6 +143,24 @@ abstract class SearchFilter extends Object {
$query->innerJoin($relationTable, "\"$relationTable\".\"$parentField\" = \"$parentBaseClass\".\"ID\"");
$query->leftJoin($componentClass, "\"$relationTable\".\"$componentField\" = \"$componentClass\".\"ID\"");
$this->model = $componentClass;
+
+ // Experimental support for user-defined relationships via a "(relName)Query" method
+ // This will likely be dropped in 2.4 for a system that makes use of Lazy Data Lists.
+ } elseif($model->hasMethod($rel.'Query')) {
+ // Get the query representing the join - it should have "$ID" in the filter
+ $newQuery = $model->{"{$rel}Query"}();
+ if($newQuery) {
+ // Get the table to join to
+ $newModel = str_replace('`','',array_shift($newQuery->from));
+ // Get the filter to use on the join
+ $ancestry = $model->getClassAncestry();
+ $newFilter = "(" . str_replace('$ID', "`{$ancestry[0]}`.`ID`" , implode(") AND (", $newQuery->where) ) . ")";
+ $query->leftJoin($newModel, $newFilter);
+ $this->model = $newModel;
+ } else {
+ $this->name = "NULL";
+ return;
+ }
}
}
}
diff --git a/security/Member.php b/security/Member.php
index 7ba49a230..4b943e0a4 100644
--- a/security/Member.php
+++ b/security/Member.php
@@ -506,6 +506,11 @@ class Member extends DataObject {
}
}
}
+
+ // save locale
+ if(!$this->Locale) {
+ $this->Locale = i18n::get_locale();
+ }
parent::onBeforeWrite();
}
@@ -860,8 +865,6 @@ class Member extends DataObject {
// Groups relation will get us into logical conflicts because
// Members are displayed within group edit form in SecurityAdmin
$fields->removeByName('Groups');
-
- $this->extend('updateCMSFields', $fields);
return $fields;
}
@@ -1226,6 +1229,13 @@ class Member_ProfileForm extends Form {
$form->saveInto($member);
$member->write();
+ $closeLink = sprintf(
+ '(%s)',
+ _t('ComplexTableField.CLOSEPOPUP', 'Close Popup')
+ );
+ $message = _t('Member.PROFILESAVESUCCESS', 'Successfully saved.') . ' ' . $closeLink;
+ $form->sessionMessage($message, 'good');
+
Director::redirectBack();
}
}
diff --git a/security/Permission.php b/security/Permission.php
index 97cb3bd5d..7bcfc7b8a 100755
--- a/security/Permission.php
+++ b/security/Permission.php
@@ -124,76 +124,78 @@ class Permission extends DataObject {
$perms_list = self::get_declared_permissions_list();
$memberID = (is_object($member)) ? $member->ID : $member;
- if(self::$declared_permissions && is_array($perms_list) &&
- !in_array($code, $perms_list)) {
- //user_error("Permission '$code' has not been declared. Use " .
- // "Permission::declare_permissions() to add this permission",
- // E_USER_WARNING);
+ /*
+ if(self::$declared_permissions && is_array($perms_list) && !in_array($code, $perms_list)) {
+ user_error(
+ "Permission '$code' has not been declared. Use " .
+ "Permission::declare_permissions() to add this permission",
+ E_USER_WARNING
+ );
}
-
+ */
+
$groupList = self::groupList($memberID);
- if($groupList) {
- $groupCSV = implode(", ", $groupList);
+ if(!$groupList) return false;
+
+ $groupCSV = implode(", ", $groupList);
- // Arg component
- switch($arg) {
- case "any":
- $argClause = "";
- break;
- case "all":
- $argClause = " AND \"Arg\" = -1";
- break;
- default:
- if(is_numeric($arg)) {
- $argClause = "AND \"Arg\" IN (-1, $arg) ";
- } else {
- user_error("Permission::checkMember: bad arg '$arg'",
- E_USER_ERROR);
- }
- }
-
- if(is_array($code)) $SQL_codeList = "'" . implode("', '", Convert::raw2sql($code)) . "'";
- else $SQL_codeList = "'" . Convert::raw2sql($code) . "'";
-
- $SQL_code = Convert::raw2sql($code);
-
- $adminFilter = (self::$admin_implies_all)
- ? ",'ADMIN'"
- : '';
-
- // Raw SQL for efficiency
- $permission = DB::query("
- SELECT \"ID\"
- FROM \"Permission\"
- WHERE (
- \"Code\" IN ($SQL_codeList $adminFilter)
- AND \"Type\" = " . self::GRANT_PERMISSION . "
- AND \"GroupID\" IN ($groupCSV)
- $argClause
- )
- ")->value();
-
- if($permission)
- return $permission;
-
-
- // Strict checking disabled?
- if(!self::$strict_checking || !$strict) {
- $hasPermission = DB::query("
- SELECT COUNT(*)
- FROM \"Permission\"
- WHERE (
- (\"Code\" IN '$SQL_code')'
- AND (\"Type\" = " . self::GRANT_PERMISSION . ")
- )
- ")->value();
- if(!$hasPermission) {
- return true;
+ // Arg component
+ switch($arg) {
+ case "any":
+ $argClause = "";
+ break;
+ case "all":
+ $argClause = " AND \"Arg\" = -1";
+ break;
+ default:
+ if(is_numeric($arg)) {
+ $argClause = "AND \"Arg\" IN (-1, $arg) ";
+ } else {
+ user_error("Permission::checkMember: bad arg '$arg'", E_USER_ERROR);
}
- }
-
- return false;
}
+
+ if(is_array($code)) {
+ $SQL_codeList = "'" . implode("', '", Convert::raw2sql($code)) . "'";
+ } else {
+ $SQL_codeList = "'" . Convert::raw2sql($code) . "'";
+ }
+
+ $SQL_code = Convert::raw2sql($code);
+
+ $adminFilter = (self::$admin_implies_all) ? ",'ADMIN'" : '';
+
+ // Raw SQL for efficiency
+ $permission = DB::query("
+ SELECT \"ID\"
+ FROM \"Permission\"
+ WHERE (
+ \"Code\" IN ($SQL_codeList $adminFilter)
+ AND \"Type\" = " . self::GRANT_PERMISSION . "
+ AND \"GroupID\" IN ($groupCSV)
+ $argClause
+ )
+ ")->value();
+
+ if($permission)
+ return $permission;
+
+ // Strict checking disabled?
+ if(!self::$strict_checking || !$strict) {
+ $hasPermission = DB::query("
+ SELECT COUNT(*)
+ FROM \"Permission\"
+ WHERE (
+ (\"Code\" IN '$SQL_code')'
+ AND (\"Type\" = " . self::GRANT_PERMISSION . ")
+ )
+ ")->value();
+ if(!$hasPermission) {
+ return true;
+ }
+ }
+
+ return false;
}
diff --git a/security/Security.php b/security/Security.php
index fe92c73d6..34d530eab 100644
--- a/security/Security.php
+++ b/security/Security.php
@@ -445,7 +445,7 @@ class Security extends Controller {
$controller = new Page_Controller($tmpPage);
$controller->init();
- $email = Convert::raw2xml($request->param('ID'));
+ $email = Convert::raw2xml($request->param('ID') . '.' . $request->getExtension());
$customisedController = $controller->customise(array(
'Title' => sprintf(_t('Security.PASSWORDSENTHEADER', "Password reset link sent to '%s'"), $email),
diff --git a/templates/Includes/Form.ss b/templates/Includes/Form.ss
index a42ab4456..d41db386f 100644
--- a/templates/Includes/Form.ss
+++ b/templates/Includes/Form.ss
@@ -6,18 +6,22 @@
<% else %>
<% end_if %>
+
-<% if Actions %>
+ <% if Actions %>
- <% control Actions %>$Field<% end_control %>
+ <% control Actions %>
+ $Field
+ <% end_control %>
-<% end_if %>
+ <% end_if %>
<% if IncludeFormTag %>
<% end_if %>
diff --git a/templates/ModelViewer.ss b/templates/ModelViewer.ss
new file mode 100644
index 000000000..a155caadb
--- /dev/null
+++ b/templates/ModelViewer.ss
@@ -0,0 +1,34 @@
+
+
+ <% base_tag %>
+ Data Model
+
+
+
+
Data Model for your project
+
+ <% control Modules %>
+
Module $Name
+
+
+
+ <% control Models %>
+
$Name <% if ParentModel %> (subclass of $ParentModel)<% end_if %>
+
Fields
+
+ <% control Fields %>
+
$Name - $Type
+ <% end_control %>
+
+
+
Relations
+
+ <% control Relations %>
+
$Name $RelationType $RelatedClass
+ <% end_control %>
+
+ <% end_control %>
+ <% end_control %>
+
+
+
diff --git a/templates/ModelViewer_dotsrc.ss b/templates/ModelViewer_dotsrc.ss
new file mode 100644
index 000000000..a7070a6f2
--- /dev/null
+++ b/templates/ModelViewer_dotsrc.ss
@@ -0,0 +1,20 @@
+digraph g {
+ orientation=portrait;
+ overlap=false;
+ splines=true;
+
+ edge[fontsize=8,len=1.5];
+ node[fontsize=10,shape=box];
+
+ <% control Modules %>
+ <% control Models %>
+ $Name [shape=record,label="{$Name|<% control Fields %>$Name\\n<% end_control %>}"];
+ <% if ParentModel %>
+ $Name -> $ParentModel [style=dotted];
+ <% end_if %>
+ <% control Relations %>
+ $Model.Name -> $RelatedClass [label="$Name\\n$RelationType"];
+ <% end_control %>
+ <% end_control %>
+ <% end_control %>
+}
diff --git a/templates/SearchForm.ss b/templates/SearchForm.ss
index ffc8ecead..9cf27f63e 100755
--- a/templates/SearchForm.ss
+++ b/templates/SearchForm.ss
@@ -1,10 +1,11 @@
diff --git a/tests/ErrorPageTest.php b/tests/ErrorPageTest.php
new file mode 100644
index 000000000..a59190104
--- /dev/null
+++ b/tests/ErrorPageTest.php
@@ -0,0 +1,31 @@
+assertTrue($errorPage instanceof ErrorPage);
+
+ /* Test the URL of the error page out to get a response */
+ $response = Director::test(Director::makeRelative($errorPage->Link()));
+
+ /* We have an HTTPResponse object for the error page */
+ $this->assertTrue($response instanceof HTTPResponse);
+
+ /* We have body text from the error page */
+ $this->assertTrue($response->getBody() != null);
+
+ /* Status code of the HTTPResponse for error page is "404" */
+ $this->assertTrue($response->getStatusCode() == '404');
+
+ /* Status message of the HTTPResponse for error page is "Not Found" */
+ $this->assertTrue($response->getStatusDescription() == 'Not Found');
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/tests/ErrorPageTest.yml b/tests/ErrorPageTest.yml
new file mode 100644
index 000000000..e85ea39d3
--- /dev/null
+++ b/tests/ErrorPageTest.yml
@@ -0,0 +1,5 @@
+ErrorPage:
+ 404:
+ Title: Page Not Found
+ URLSegment: page-not-found
+ ErrorCode: 404
\ No newline at end of file
diff --git a/tests/ManifestBuilderTest.php b/tests/ManifestBuilderTest.php
index a0f168486..0660f1185 100644
--- a/tests/ManifestBuilderTest.php
+++ b/tests/ManifestBuilderTest.php
@@ -74,6 +74,8 @@ class ManifestBuilderTest extends SapphireTest {
protected static $test_fixture_project;
function setUp() {
+ parent::setUp();
+
// Trick the auto-loder into loading this class before we muck with the manifest
new TokenisedRegularExpression(null);
@@ -131,6 +133,8 @@ class ManifestBuilderTest extends SapphireTest {
// Kill the folder after we're done
$baseFolder = TEMP_FOLDER . '/manifest-test/';
Filesystem::removeFolder($baseFolder);
+
+ parent::tearDown();
}
}
diff --git a/tests/SiteTreePermissionsTest.php b/tests/SiteTreePermissionsTest.php
index 9414eb03a..fb49246cd 100644
--- a/tests/SiteTreePermissionsTest.php
+++ b/tests/SiteTreePermissionsTest.php
@@ -18,6 +18,36 @@ class SiteTreePermissionsTest extends FunctionalTest {
$this->autoFollowRedirection = false;
}
+ function testAccessTabOnlyDisplaysWithGrantAccessPermissions() {
+ $page = $this->objFromFixture('Page', 'standardpage');
+
+ $subadminuser = $this->objFromFixture('Member', 'subadmin');
+ $this->session()->inst_set('loggedInAs', $subadminuser->ID);
+ $fields = $page->getCMSFields();
+ $this->assertFalse(
+ $fields->dataFieldByName('CanViewType')->isReadonly(),
+ 'Users with SITETREE_GRANT_ACCESS permission can change "view" permissions in cms fields'
+ );
+ $this->assertFalse(
+ $fields->dataFieldByName('CanEditType')->isReadonly(),
+ 'Users with SITETREE_GRANT_ACCESS permission can change "edit" permissions in cms fields'
+ );
+
+ $editoruser = $this->objFromFixture('Member', 'editor');
+ $this->session()->inst_set('loggedInAs', $editoruser->ID);
+ $fields = $page->getCMSFields();
+ $this->assertTrue(
+ $fields->dataFieldByName('CanViewType')->isReadonly(),
+ 'Users without SITETREE_GRANT_ACCESS permission cannot change "view" permissions in cms fields'
+ );
+ $this->assertTrue(
+ $fields->dataFieldByName('CanEditType')->isReadonly(),
+ 'Users without SITETREE_GRANT_ACCESS permission cannot change "edit" permissions in cms fields'
+ );
+
+ $this->session()->inst_set('loggedInAs', null);
+ }
+
function testRestrictedViewLoggedInUsers() {
$page = $this->objFromFixture('Page', 'restrictedViewLoggedInUsers');
@@ -30,7 +60,7 @@ class SiteTreePermissionsTest extends FunctionalTest {
$response = $this->get($page->URLSegment);
$this->assertEquals(
$response->getStatusCode(),
- 403,
+ 302,
'Unauthenticated members cant view a page marked as "Viewable for any logged in users"'
);
@@ -62,7 +92,7 @@ class SiteTreePermissionsTest extends FunctionalTest {
$response = $this->get($page->URLSegment);
$this->assertEquals(
$response->getStatusCode(),
- 403,
+ 302,
'Unauthenticated members cant view a page marked as "Viewable by these groups"'
);
@@ -76,7 +106,7 @@ class SiteTreePermissionsTest extends FunctionalTest {
$response = $this->get($page->URLSegment);
$this->assertEquals(
$response->getStatusCode(),
- 403,
+ 302,
'Authenticated members cant view a page marked as "Viewable by these groups" if theyre not in the listed groups'
);
$this->session()->inst_set('loggedInAs', null);
@@ -159,7 +189,7 @@ class SiteTreePermissionsTest extends FunctionalTest {
$response = $this->get($childPage->URLSegment);
$this->assertEquals(
$response->getStatusCode(),
- 403,
+ 302,
'Unauthenticated members cant view a page marked as "Viewable by these groups" by inherited permission'
);
diff --git a/tests/SiteTreePermissionsTest.yml b/tests/SiteTreePermissionsTest.yml
index a9652b8c6..c0c6fdff0 100644
--- a/tests/SiteTreePermissionsTest.yml
+++ b/tests/SiteTreePermissionsTest.yml
@@ -3,11 +3,13 @@ Permission:
Code: CMS_ACCESS_CMSMain
cmsmain2:
Code: CMS_ACCESS_CMSMain
+ grantaccess:
+ Code: SITETREE_GRANT_ACCESS
Group:
subadmingroup:
Title: Create, edit and delete pages
Code: subadmingroup
- Permissions: =>Permission.cmsmain1
+ Permissions: =>Permission.cmsmain1,=>Permission.grantaccess
editorgroup:
Title: Edit existing pages
Code: editorgroup
@@ -28,6 +30,8 @@ Member:
Password: test
Groups: =>Group.websiteusers
Page:
+ standardpage:
+ URLSegment: standardpage
restrictedViewLoggedInUsers:
CanViewType: LoggedInUsers
URLSegment: restrictedViewLoggedInUsers
diff --git a/tests/forms/CheckboxSetFieldTest.php b/tests/forms/CheckboxSetFieldTest.php
index a3b237ebc..0dd700ced 100644
--- a/tests/forms/CheckboxSetFieldTest.php
+++ b/tests/forms/CheckboxSetFieldTest.php
@@ -4,6 +4,14 @@ class CheckboxSetFieldTest extends SapphireTest {
static $fixture_file = 'sapphire/tests/forms/CheckboxSetFieldTest.yml';
+ function testAddExtraClass() {
+ /* CheckboxSetField has an extra class name and is in the HTML the field returns */
+ $cboxSetField = new CheckboxSetField('FeelingOk', 'Are you feeling ok?', array(0 => 'No', 1 => 'Yes'), '', null, '(Select one)');
+ $cboxSetField->addExtraClass('thisIsMyExtraClassForCheckboxSetField');
+ preg_match('/thisIsMyExtraClassForCheckboxSetField/', $cboxSetField->Field(), $matches);
+ $this->assertTrue($matches[0] == 'thisIsMyExtraClassForCheckboxSetField');
+ }
+
function testSaveWithNothingSelected() {
$article = $this->fixture->objFromFixture('CheckboxSetFieldTest_Article', 'articlewithouttags');
diff --git a/tests/forms/DropdownFieldTest.php b/tests/forms/DropdownFieldTest.php
index 08bf6e8c3..b2e8baf10 100644
--- a/tests/forms/DropdownFieldTest.php
+++ b/tests/forms/DropdownFieldTest.php
@@ -5,6 +5,14 @@
*/
class DropdownFieldTest extends SapphireTest {
+ function testAddExtraClass() {
+ /* DropdownField has an extra class name and is in the HTML the field returns */
+ $dropdownField = new DropdownField('FeelingOk', 'Are you feeling ok?', array(0 => 'No', 1 => 'Yes'), '', null, '(Select one)');
+ $dropdownField->addExtraClass('thisIsMyExtraClassForDropdownField');
+ preg_match('/thisIsMyExtraClassForDropdownField/', $dropdownField->Field(), $matches);
+ $this->assertTrue($matches[0] == 'thisIsMyExtraClassForDropdownField');
+ }
+
function testGetSource() {
$source = array(1=>'one');
$field = new DropdownField('Field', null, $source);
diff --git a/tests/forms/FieldSetTest.php b/tests/forms/FieldSetTest.php
index 4d76559c2..a5b854d5c 100644
--- a/tests/forms/FieldSetTest.php
+++ b/tests/forms/FieldSetTest.php
@@ -670,5 +670,20 @@ class FieldSetTest extends SapphireTest {
unset($set);
}
+
+ function testMakeFieldReadonly() {
+ $fieldSet = new FieldSet(
+ new TabSet('Root', new Tab('Main',
+ new TextField('A'),
+ new TextField('B')
+ )
+ ));
+
+ $fieldSet->makeFieldReadonly('A');
+ $this->assertTrue(
+ $fieldSet->dataFieldByName('A')->isReadonly(),
+ 'Field nested inside a TabSet and FieldSet can be marked readonly by FieldSet->makeFieldReadonly()'
+ );
+ }
}
?>
\ No newline at end of file
diff --git a/tests/forms/FormFieldTest.php b/tests/forms/FormFieldTest.php
new file mode 100644
index 000000000..02b58a558
--- /dev/null
+++ b/tests/forms/FormFieldTest.php
@@ -0,0 +1,89 @@
+addExtraClass('thisIsMyClassNameForTheFormField');
+ preg_match('/thisIsMyClassNameForTheFormField/', $textField->Field(), $matches);
+ $this->assertTrue($matches[0] == 'thisIsMyClassNameForTheFormField');
+
+ /* EmailField has an extra class name and is in the HTML the field returns */
+ $emailField = new EmailField('Email');
+ $emailField->addExtraClass('thisIsMyExtraClassForEmailField');
+ preg_match('/thisIsMyExtraClassForEmailField/', $emailField->Field(), $matches);
+ $this->assertTrue($matches[0] == 'thisIsMyExtraClassForEmailField');
+
+ /* OptionsetField has an extra class name and is in the HTML the field returns */
+ $optionsetField = new OptionsetField('FeelingOk', 'Are you feeling ok?', array(0 => 'No', 1 => 'Yes'), '', null, '(Select one)');
+ $optionsetField->addExtraClass('thisIsMyExtraClassForOptionsetField');
+ preg_match('/thisIsMyExtraClassForOptionsetField/', $optionsetField->Field(), $matches);
+ $this->assertTrue($matches[0] == 'thisIsMyExtraClassForOptionsetField');
+ }
+
+ function testEveryFieldTransformsReadonlyAsClone() {
+ $fieldClasses = ClassInfo::subclassesFor('FormField');
+ foreach($fieldClasses as $fieldClass) {
+ $reflectionClass = new ReflectionClass($fieldClass);
+ if(!$reflectionClass->isInstantiable()) continue;
+ $constructor = $reflectionClass->getMethod('__construct');
+ if($constructor->getNumberOfRequiredParameters() > 1) continue;
+ if($fieldClass == 'CompositeField' || is_subclass_of($fieldClass, 'CompositeField')) continue;
+
+ $instance = new $fieldClass("{$fieldClass}_instance");
+
+ $isReadonlyBefore = $instance->isReadonly();
+ $readonlyInstance = $instance->performReadonlyTransformation();
+ $this->assertEquals(
+ $isReadonlyBefore,
+ $instance->isReadonly(),
+ "FormField class '{$fieldClass} retains its readonly state after calling performReadonlyTransformation()"
+ );
+ $this->assertTrue(
+ $readonlyInstance->isReadonly(),
+ "FormField class '{$fieldClass} returns a valid readonly representation as of isReadonly()"
+ );
+ $this->assertNotSame(
+ $readonlyInstance,
+ $instance,
+ "FormField class '{$fieldClass} returns a valid cloned readonly representation"
+ );
+ }
+ }
+
+ function testEveryFieldTransformsDisabledAsClone() {
+ $fieldClasses = ClassInfo::subclassesFor('FormField');
+ foreach($fieldClasses as $fieldClass) {
+ $reflectionClass = new ReflectionClass($fieldClass);
+ if(!$reflectionClass->isInstantiable()) continue;
+ $constructor = $reflectionClass->getMethod('__construct');
+ if($constructor->getNumberOfRequiredParameters() > 1) continue;
+ if($fieldClass == 'CompositeField' || is_subclass_of($fieldClass, 'CompositeField')) continue;
+
+ $instance = new $fieldClass("{$fieldClass}_instance");
+
+ $isDisabledBefore = $instance->isDisabled();
+ $disabledInstance = $instance->performDisabledTransformation();
+ $this->assertEquals(
+ $isDisabledBefore,
+ $instance->isDisabled(),
+ "FormField class '{$fieldClass} retains its disabled state after calling performDisabledTransformation()"
+ );
+ $this->assertTrue(
+ $disabledInstance->isDisabled(),
+ "FormField class '{$fieldClass} returns a valid disabled representation as of isDisabled()"
+ );
+ $this->assertNotSame(
+ $disabledInstance,
+ $instance,
+ "FormField class '{$fieldClass} returns a valid cloned disabled representation"
+ );
+ }
+ }
+
+}
+?>
\ No newline at end of file
diff --git a/tests/i18n/i18nTest.php b/tests/i18n/i18nTest.php
index 52ee53aa9..2817a7a65 100644
--- a/tests/i18n/i18nTest.php
+++ b/tests/i18n/i18nTest.php
@@ -62,6 +62,8 @@ class i18nTest extends SapphireTest {
unset($_TEMPLATE_MANIFEST['i18nTestModuleInclude.ss']);
i18n::set_locale('en_US');
+
+ parent::tearDown();
}
function testGetExistingTranslations() {
diff --git a/tests/i18n/i18nTextCollectorTest.php b/tests/i18n/i18nTextCollectorTest.php
index 8655c2ca0..e5f3fcb8b 100644
--- a/tests/i18n/i18nTextCollectorTest.php
+++ b/tests/i18n/i18nTextCollectorTest.php
@@ -60,6 +60,8 @@ class i18nTextCollectorTest extends SapphireTest {
global $_TEMPLATE_MANIFEST;
unset($_TEMPLATE_MANIFEST['i18nTestModule.ss']);
unset($_TEMPLATE_MANIFEST['i18nTestModuleInclude.ss']);
+
+ parent::tearDown();
}
function testCollectFromTemplateSimple() {
diff --git a/tests/search/SearchFormTest.php b/tests/search/SearchFormTest.php
index f1afec84f..65638e2ca 100644
--- a/tests/search/SearchFormTest.php
+++ b/tests/search/SearchFormTest.php
@@ -17,14 +17,6 @@ class SearchFormTest extends FunctionalTest {
$holderPage = $this->objFromFixture('SiteTree', 'searchformholder');
$this->mockController = new ContentController($holderPage);
- $this->mockController->setSession(new Session(Controller::curr()->getSession()));
- $this->mockController->pushCurrent();
- }
-
- function tearDown() {
- $this->mockController->popCurrent();
-
- parent::tearDown();
}
function testPublishedPagesMatchedByTitle() {