Skip to content

Commit

Permalink
Merge pull request silverstripe#2850 from kinglozzer/2827-member-extend
Browse files Browse the repository at this point in the history
FIX: Rewrite Member getCMSFields to ensure updateCMSFields is only run once (fixes silverstripe#2827)
  • Loading branch information
tractorcow committed Mar 4, 2014
2 parents ccb7919 + d91c7d1 commit 1cc366f
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 110 deletions.
219 changes: 109 additions & 110 deletions security/Member.php
Original file line number Diff line number Diff line change
Expand Up @@ -1202,125 +1202,124 @@ public function memberNotInGroups($groupList, $memberGroups = null){
* editing this member.
*/
public function getCMSFields() {
require_once('Zend/Date.php');

$fields = parent::getCMSFields();

$mainFields = $fields->fieldByName("Root")->fieldByName("Main")->Children;

$password = new ConfirmedPasswordField(
'Password',
null,
null,
null,
true // showOnClick
);
$password->setCanBeEmpty(true);
if(!$this->ID) $password->showOnClick = false;
$mainFields->replaceField('Password', $password);

$mainFields->replaceField('Locale', new DropdownField(
"Locale",
_t('Member.INTERFACELANG', "Interface Language", 'Language of the CMS'),
i18n::get_existing_translations()
));

$mainFields->removeByName('RememberLoginToken');
$mainFields->removeByName('AutoLoginHash');
$mainFields->removeByName('AutoLoginExpired');
$mainFields->removeByName('PasswordEncryption');
$mainFields->removeByName('PasswordExpiry');
$mainFields->removeByName('LockedOutUntil');

if(!self::config()->lock_out_after_incorrect_logins) {
$mainFields->removeByName('FailedLoginCount');
}

$mainFields->removeByName('Salt');
$mainFields->removeByName('NumVisit');
require_once 'Zend/Date.php';

$self = $this;
$this->beforeUpdateCMSFields(function($fields) use ($self) {
$mainFields = $fields->fieldByName("Root")->fieldByName("Main")->Children;

$password = new ConfirmedPasswordField(
'Password',
null,
null,
null,
true // showOnClick
);
$password->setCanBeEmpty(true);
if( ! $self->ID) $password->showOnClick = false;
$mainFields->replaceField('Password', $password);

$mainFields->replaceField('Locale', new DropdownField(
"Locale",
_t('Member.INTERFACELANG', "Interface Language", 'Language of the CMS'),
i18n::get_existing_translations()
));

$mainFields->makeFieldReadonly('LastVisited');
$mainFields->removeByName('RememberLoginToken');
$mainFields->removeByName('AutoLoginHash');
$mainFields->removeByName('AutoLoginExpired');
$mainFields->removeByName('PasswordEncryption');
$mainFields->removeByName('PasswordExpiry');
$mainFields->removeByName('LockedOutUntil');

if( ! $self->config()->lock_out_after_incorrect_logins) {
$mainFields->removeByName('FailedLoginCount');
}

$mainFields->removeByName('Salt');
$mainFields->removeByName('NumVisit');

$fields->removeByName('Subscriptions');
$mainFields->makeFieldReadonly('LastVisited');

// Groups relation will get us into logical conflicts because
// Members are displayed within group edit form in SecurityAdmin
$fields->removeByName('Groups');
$fields->removeByName('Subscriptions');

if(Permission::check('EDIT_PERMISSIONS')) {
$groupsMap = array();
foreach(Group::get() as $group) {
// Listboxfield values are escaped, use ASCII char instead of »
$groupsMap[$group->ID] = $group->getBreadcrumbs(' > ');
}
asort($groupsMap);
$fields->addFieldToTab('Root.Main',
ListboxField::create('DirectGroups', singleton('Group')->i18n_plural_name())
->setMultiple(true)
->setSource($groupsMap)
->setAttribute(
'data-placeholder',
_t('Member.ADDGROUP', 'Add group', 'Placeholder text for a dropdown')
)
);
// Groups relation will get us into logical conflicts because
// Members are displayed within group edit form in SecurityAdmin
$fields->removeByName('Groups');

// Add permission field (readonly to avoid complicated group assignment logic).
// This should only be available for existing records, as new records start
// with no permissions until they have a group assignment anyway.
if($this->ID) {
$permissionsField = new PermissionCheckboxSetField_Readonly(
'Permissions',
false,
'Permission',
'GroupID',
// we don't want parent relationships, they're automatically resolved in the field
$this->getManyManyComponents('Groups')
if(Permission::check('EDIT_PERMISSIONS')) {
$groupsMap = array();
foreach(Group::get() as $group) {
// Listboxfield values are escaped, use ASCII char instead of »
$groupsMap[$group->ID] = $group->getBreadcrumbs(' > ');
}
asort($groupsMap);
$fields->addFieldToTab('Root.Main',
ListboxField::create('DirectGroups', singleton('Group')->i18n_plural_name())
->setMultiple(true)
->setSource($groupsMap)
->setAttribute(
'data-placeholder',
_t('Member.ADDGROUP', 'Add group', 'Placeholder text for a dropdown')
)
);
$fields->findOrMakeTab('Root.Permissions', singleton('Permission')->i18n_plural_name());
$fields->addFieldToTab('Root.Permissions', $permissionsField);
}
}

$permissionsTab = $fields->fieldByName("Root")->fieldByName('Permissions');
if($permissionsTab) $permissionsTab->addExtraClass('readonly');

$defaultDateFormat = Zend_Locale_Format::getDateFormat(new Zend_Locale($this->Locale));
$dateFormatMap = array(
'MMM d, yyyy' => Zend_Date::now()->toString('MMM d, yyyy'),
'yyyy/MM/dd' => Zend_Date::now()->toString('yyyy/MM/dd'),
'MM/dd/yyyy' => Zend_Date::now()->toString('MM/dd/yyyy'),
'dd/MM/yyyy' => Zend_Date::now()->toString('dd/MM/yyyy'),
);
$dateFormatMap[$defaultDateFormat] = Zend_Date::now()->toString($defaultDateFormat)
. sprintf(' (%s)', _t('Member.DefaultDateTime', 'default'));
$mainFields->push(
$dateFormatField = new MemberDatetimeOptionsetField(
'DateFormat',
$this->fieldLabel('DateFormat'),
$dateFormatMap
)
);
$dateFormatField->setValue($this->DateFormat);

$defaultTimeFormat = Zend_Locale_Format::getTimeFormat(new Zend_Locale($this->Locale));
$timeFormatMap = array(
'h:mm a' => Zend_Date::now()->toString('h:mm a'),
'H:mm' => Zend_Date::now()->toString('H:mm'),
);
$timeFormatMap[$defaultTimeFormat] = Zend_Date::now()->toString($defaultTimeFormat)
. sprintf(' (%s)', _t('Member.DefaultDateTime', 'default'));
$mainFields->push(
$timeFormatField = new MemberDatetimeOptionsetField(
'TimeFormat',
$this->fieldLabel('TimeFormat'),
$timeFormatMap
)
);
$timeFormatField->setValue($this->TimeFormat);
// Add permission field (readonly to avoid complicated group assignment logic).
// This should only be available for existing records, as new records start
// with no permissions until they have a group assignment anyway.
if($self->ID) {
$permissionsField = new PermissionCheckboxSetField_Readonly(
'Permissions',
false,
'Permission',
'GroupID',
// we don't want parent relationships, they're automatically resolved in the field
$self->getManyManyComponents('Groups')
);
$fields->findOrMakeTab('Root.Permissions', singleton('Permission')->i18n_plural_name());
$fields->addFieldToTab('Root.Permissions', $permissionsField);
}
}

$this->extend('updateCMSFields', $fields);
$permissionsTab = $fields->fieldByName("Root")->fieldByName('Permissions');
if($permissionsTab) $permissionsTab->addExtraClass('readonly');

$defaultDateFormat = Zend_Locale_Format::getDateFormat(new Zend_Locale($self->Locale));
$dateFormatMap = array(
'MMM d, yyyy' => Zend_Date::now()->toString('MMM d, yyyy'),
'yyyy/MM/dd' => Zend_Date::now()->toString('yyyy/MM/dd'),
'MM/dd/yyyy' => Zend_Date::now()->toString('MM/dd/yyyy'),
'dd/MM/yyyy' => Zend_Date::now()->toString('dd/MM/yyyy'),
);
$dateFormatMap[$defaultDateFormat] = Zend_Date::now()->toString($defaultDateFormat)
. sprintf(' (%s)', _t('Member.DefaultDateTime', 'default'));
$mainFields->push(
$dateFormatField = new MemberDatetimeOptionsetField(
'DateFormat',
$self->fieldLabel('DateFormat'),
$dateFormatMap
)
);
$dateFormatField->setValue($self->DateFormat);

$defaultTimeFormat = Zend_Locale_Format::getTimeFormat(new Zend_Locale($self->Locale));
$timeFormatMap = array(
'h:mm a' => Zend_Date::now()->toString('h:mm a'),
'H:mm' => Zend_Date::now()->toString('H:mm'),
);
$timeFormatMap[$defaultTimeFormat] = Zend_Date::now()->toString($defaultTimeFormat)
. sprintf(' (%s)', _t('Member.DefaultDateTime', 'default'));
$mainFields->push(
$timeFormatField = new MemberDatetimeOptionsetField(
'TimeFormat',
$self->fieldLabel('TimeFormat'),
$timeFormatMap
)
);
$timeFormatField->setValue($self->TimeFormat);
});

return $fields;
return parent::getCMSFields();
}

/**
Expand Down
28 changes: 28 additions & 0 deletions tests/security/MemberTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,22 @@ public function testOnChangeGroups() {
'Adding new admin group relation is allowed for admin members'
);
}

/**
* Test that extensions using updateCMSFields() are applied correctly
*/
public function testUpdateCMSFields() {
Member::add_extension('MemberTest_FieldsExtension');

$member = singleton('Member');
$fields = $member->getCMSFields();

$this->assertNotNull($fields->dataFieldByName('Email'), 'Scaffolded fields are retained');
$this->assertNull($fields->dataFieldByName('Salt'), 'Field modifications run correctly');
$this->assertNotNull($fields->dataFieldByName('TestMemberField'), 'Extension is applied correctly');

Member::remove_extension('MemberTest_FieldsExtension');
}

/**
* Test that all members are returned
Expand Down Expand Up @@ -827,6 +843,18 @@ public function canView($member = null) {
}
}

/**
* @package framework
* @subpackage tests
*/
class MemberTest_FieldsExtension extends DataExtension implements TestOnly {

public function updateCMSFields(FieldList $fields) {
$fields->addFieldToTab('Root.Main', new TextField('TestMemberField', 'Test'));
}

}

/**
* @package framework
* @subpackage tests
Expand Down

0 comments on commit 1cc366f

Please sign in to comment.