mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
API CHANGE Removed MemberTableField, use GridField with GridFieldConfig_RelationEditor instead
This commit is contained in:
parent
8da89c6f7c
commit
0117b32fee
@ -1,370 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Enhances {ComplexTableField} with the ability to list groups and given members.
|
|
||||||
* It is based around groups, so it deletes Members from a Group rather than from the entire system.
|
|
||||||
*
|
|
||||||
* In contrast to the original implementation, the URL-parameters "ParentClass" and "ParentID" are used
|
|
||||||
* to specify "Group" (hardcoded) and the GroupID-relation.
|
|
||||||
*
|
|
||||||
* @todo write a better description about what this field does.
|
|
||||||
*
|
|
||||||
* Returns either:
|
|
||||||
* - provided members
|
|
||||||
* - members of a provided group
|
|
||||||
* - all members
|
|
||||||
* - members based on a search-query
|
|
||||||
*
|
|
||||||
* @package cms
|
|
||||||
* @subpackage security
|
|
||||||
*/
|
|
||||||
class MemberTableField extends ComplexTableField {
|
|
||||||
|
|
||||||
protected $members;
|
|
||||||
|
|
||||||
protected $hidePassword;
|
|
||||||
|
|
||||||
protected $detailFormValidator;
|
|
||||||
|
|
||||||
protected $group;
|
|
||||||
|
|
||||||
protected $template = 'MemberTableField';
|
|
||||||
|
|
||||||
public $popupClass = 'MemberTableField_Popup';
|
|
||||||
|
|
||||||
public $itemClass = 'MemberTableField_Item';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the page size for this table.
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public static $page_size = 20;
|
|
||||||
|
|
||||||
protected $permissions = array(
|
|
||||||
"add",
|
|
||||||
"edit",
|
|
||||||
"show",
|
|
||||||
"delete",
|
|
||||||
'inlineadd'
|
|
||||||
//"export",
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor method for MemberTableField.
|
|
||||||
*
|
|
||||||
* @param Controller $controller Controller class which created this field
|
|
||||||
* @param string $name Name of the field (e.g. "Members")
|
|
||||||
* @param mixed $group Can be the ID of a Group instance, or a Group instance itself
|
|
||||||
* @param SS_List $members Optional set of Members to set as the source items for this field
|
|
||||||
* @param boolean $hidePassword Hide the password field or not in the summary?
|
|
||||||
*/
|
|
||||||
function __construct($controller, $name, $group = null, $members = null, $hidePassword = true) {
|
|
||||||
|
|
||||||
if(!$members) {
|
|
||||||
if($group) {
|
|
||||||
if(is_numeric($group)) $group = DataObject::get_by_id('Group', $group);
|
|
||||||
$this->group = $group;
|
|
||||||
$members = $group->Members();
|
|
||||||
|
|
||||||
} elseif(isset($_REQUEST['ctf'][$this->getName()]["ID"]) && is_numeric($_REQUEST['ctf'][$this->getName()]["ID"])) {
|
|
||||||
throw new Exception("Is this still being used? It's a hack and we should remove it.");
|
|
||||||
$group = DataObject::get_by_id('Group', $_REQUEST['ctf'][$this->getName()]["ID"]);
|
|
||||||
$this->group = $group;
|
|
||||||
$members = $group->Members();
|
|
||||||
} else {
|
|
||||||
$members = DataObject::get("Member");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$SNG_member = singleton('Member');
|
|
||||||
$fieldList = $SNG_member->summaryFields();
|
|
||||||
$memberDbFields = $SNG_member->db();
|
|
||||||
$csvFieldList = array();
|
|
||||||
|
|
||||||
foreach($memberDbFields as $field => $dbFieldType) {
|
|
||||||
$csvFieldList[$field] = $field;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$hidePassword) {
|
|
||||||
$fieldList["SetPassword"] = "Password";
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->hidePassword = $hidePassword;
|
|
||||||
|
|
||||||
// Add a search filter
|
|
||||||
$SQL_search = isset($_REQUEST['MemberSearch']) ? Convert::raw2sql($_REQUEST['MemberSearch']) : null;
|
|
||||||
if(!empty($_REQUEST['MemberSearch'])) {
|
|
||||||
$searchFilters = array();
|
|
||||||
foreach($SNG_member->searchableFields() as $fieldName => $fieldSpec) {
|
|
||||||
if(strpos($fieldName, '.') === false) $searchFilters[] = "\"$fieldName\" LIKE '%{$SQL_search}%'";
|
|
||||||
}
|
|
||||||
$members = $members->where('(' . implode(' OR ', $searchFilters) . ')');
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct($controller, $name, $members, $fieldList);
|
|
||||||
|
|
||||||
$this->setFieldListCsv($csvFieldList);
|
|
||||||
$this->setPageSize($this->stat('page_size'));
|
|
||||||
}
|
|
||||||
|
|
||||||
function FieldHolder() {
|
|
||||||
$ret = parent::FieldHolder();
|
|
||||||
|
|
||||||
Requirements::javascript(SAPPHIRE_DIR . "/thirdparty/scriptaculous/controls.js");
|
|
||||||
Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/MemberTableField.js');
|
|
||||||
Requirements::javascript(SAPPHIRE_ADMIN_DIR . "/javascript/MemberTableField_popup.js");
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
function SearchForm() {
|
|
||||||
$groupID = (isset($this->group)) ? $this->group->ID : 0;
|
|
||||||
$query = isset($_GET['MemberSearch']) ? $_GET['MemberSearch'] : null;
|
|
||||||
|
|
||||||
$searchFields = new FieldGroup(
|
|
||||||
new TextField('MemberSearch', _t('MemberTableField.SEARCH', 'Search'), $query),
|
|
||||||
new HiddenField("ctf[ID]", '', $groupID),
|
|
||||||
new HiddenField('MemberFieldName', '', $this->name),
|
|
||||||
new HiddenField('MemberDontShowPassword', '', $this->hidePassword)
|
|
||||||
);
|
|
||||||
|
|
||||||
$actionFields = new LiteralField('MemberFilterButton','<input type="submit" class="action" name="MemberFilterButton" value="'._t('MemberTableField.FILTER', 'Filter').'" id="MemberFilterButton"/>');
|
|
||||||
|
|
||||||
$fieldContainer = new FieldGroup(
|
|
||||||
$searchFields,
|
|
||||||
$actionFields
|
|
||||||
);
|
|
||||||
|
|
||||||
return $fieldContainer->FieldHolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add existing member to group rather than creating a new member
|
|
||||||
*/
|
|
||||||
function addtogroup() {
|
|
||||||
// Protect against CSRF on destructive action
|
|
||||||
$token = $this->getForm()->getSecurityToken();
|
|
||||||
if(!$token->checkRequest($this->controller->getRequest())) return $this->httpError(400);
|
|
||||||
|
|
||||||
$data = $_REQUEST;
|
|
||||||
|
|
||||||
$groupID = (isset($data['ctf']['ID'])) ? $data['ctf']['ID'] : null;
|
|
||||||
|
|
||||||
if(!is_numeric($groupID)) {
|
|
||||||
FormResponse::status_messsage(_t('MemberTableField.ADDINGFIELD', 'Adding failed'), 'bad');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get existing record either by ID or unique identifier.
|
|
||||||
$identifierField = Member::get_unique_identifier_field();
|
|
||||||
$className = 'Member';
|
|
||||||
$record = null;
|
|
||||||
if(isset($data[$identifierField])) {
|
|
||||||
$record = DataObject::get_one(
|
|
||||||
$className,
|
|
||||||
sprintf('"%s" = \'%s\'', $identifierField, $data[$identifierField])
|
|
||||||
);
|
|
||||||
|
|
||||||
if($record && !$record->canEdit()) return $this->httpError('401');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fall back to creating a new record
|
|
||||||
if(!$record) $record = new $className();
|
|
||||||
|
|
||||||
// Update an existing record, or populate a new one.
|
|
||||||
// If values on an existing (autocompleted) record have been changed,
|
|
||||||
// they will overwrite current data. We need to unset 'ID'
|
|
||||||
// record as it points to the group rather than the member record, and would
|
|
||||||
// cause the member to be written to a potentially existing record.
|
|
||||||
unset($data['ID']);
|
|
||||||
$record->update($data);
|
|
||||||
|
|
||||||
// Validate record, mainly password restrictions.
|
|
||||||
// Note: Doesn't use Member_Validator
|
|
||||||
$valid = $record->validate();
|
|
||||||
if($valid->valid()) {
|
|
||||||
$record->write();
|
|
||||||
$this->getDataList()->add($record);
|
|
||||||
|
|
||||||
$this->sourceItems();
|
|
||||||
|
|
||||||
// TODO add javascript to highlight added row (problem: might not show up due to sorting/filtering)
|
|
||||||
FormResponse::update_dom_id($this->id(), $this->renderWith($this->template), true);
|
|
||||||
FormResponse::status_message(
|
|
||||||
_t(
|
|
||||||
'MemberTableField.ADDEDTOGROUP','Added member to group'
|
|
||||||
),
|
|
||||||
'good'
|
|
||||||
);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$message = sprintf(
|
|
||||||
_t(
|
|
||||||
'MemberTableField.ERRORADDINGUSER',
|
|
||||||
'There was an error adding the user to the group: %s'
|
|
||||||
),
|
|
||||||
Convert::raw2xml($valid->starredList())
|
|
||||||
);
|
|
||||||
|
|
||||||
FormResponse::status_message($message, 'bad');
|
|
||||||
}
|
|
||||||
|
|
||||||
return FormResponse::respond();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* #################################
|
|
||||||
* Custom Functions
|
|
||||||
* #################################
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Group
|
|
||||||
*/
|
|
||||||
function getGroup() {
|
|
||||||
return $this->group;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add existing member to group by name (with JS-autocompletion)
|
|
||||||
*/
|
|
||||||
function AddRecordForm() {
|
|
||||||
$fields = new FieldList();
|
|
||||||
foreach($this->FieldList() as $fieldName => $fieldTitle) {
|
|
||||||
// If we're adding the set password field, we want to hide the text from any peeping eyes
|
|
||||||
if($fieldName == 'SetPassword') {
|
|
||||||
$fields->push(new PasswordField($fieldName));
|
|
||||||
} else {
|
|
||||||
$fields->push(new TextField($fieldName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if($this->group) {
|
|
||||||
$fields->push(new HiddenField('ctf[ID]', null, $this->group->ID));
|
|
||||||
}
|
|
||||||
$actions = new FieldList(
|
|
||||||
new FormAction('addtogroup', _t('MemberTableField.ADD','Add'))
|
|
||||||
);
|
|
||||||
|
|
||||||
return new TabularStyle(
|
|
||||||
new NestedForm(
|
|
||||||
new Form(
|
|
||||||
$this,
|
|
||||||
'AddRecordForm',
|
|
||||||
$fields,
|
|
||||||
$actions
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function AddForm() {
|
|
||||||
$form = parent::AddForm();
|
|
||||||
|
|
||||||
// Set default groups - also implemented in MemberTableField_Popup::__construct()
|
|
||||||
if($this->group) {
|
|
||||||
$groupsField = $form->Fields()->dataFieldByName('Groups');
|
|
||||||
// TODO Needs to be a string value (not int) because of TreeMultiselectField->getItems(),
|
|
||||||
// see http://open.silverstripe.org/ticket/5836
|
|
||||||
if($groupsField) $groupsField->setValue((string)$this->group->ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $form;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Same behaviour as parent class, but adds the
|
|
||||||
* member to the passed GroupID.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function saveComplexTableField($data, $form, $params) {
|
|
||||||
$className = $this->sourceClass();
|
|
||||||
$childData = new $className();
|
|
||||||
|
|
||||||
// Needs to write before saveInto() to ensure the 'Groups' TreeMultiselectField saves
|
|
||||||
$childData->write();
|
|
||||||
|
|
||||||
try {
|
|
||||||
$form->saveInto($childData);
|
|
||||||
$childData->write();
|
|
||||||
} catch(ValidationException $e) {
|
|
||||||
$form->sessionMessage($e->getResult()->message(), 'bad');
|
|
||||||
return Director::redirectBack();
|
|
||||||
}
|
|
||||||
|
|
||||||
$closeLink = sprintf(
|
|
||||||
'<small><a href="' . $_SERVER['HTTP_REFERER'] . '" onclick="javascript:window.top.GB_hide(); return false;">(%s)</a></small>',
|
|
||||||
_t('ComplexTableField.CLOSEPOPUP', 'Close Popup')
|
|
||||||
);
|
|
||||||
$message = sprintf(
|
|
||||||
_t('ComplexTableField.SUCCESSADD', 'Added %s %s %s'),
|
|
||||||
$childData->singular_name(),
|
|
||||||
'<a href="' . $this->Link() . '">' . htmlspecialchars($childData->Title, ENT_QUOTES, 'UTF-8') . '</a>',
|
|
||||||
$closeLink
|
|
||||||
);
|
|
||||||
$form->sessionMessage($message, 'good');
|
|
||||||
|
|
||||||
$this->controller->redirectBack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Popup window for {@link MemberTableField}.
|
|
||||||
* @package cms
|
|
||||||
* @subpackage security
|
|
||||||
*/
|
|
||||||
class MemberTableField_Popup extends ComplexTableField_Popup {
|
|
||||||
|
|
||||||
function __construct($controller, $name, $fields, $validator, $readonly, $dataObject) {
|
|
||||||
$group = ($controller instanceof MemberTableField) ? $controller->getGroup() : $controller->getParentController()->getGroup();
|
|
||||||
// Set default groups - also implemented in AddForm()
|
|
||||||
if($group) {
|
|
||||||
$groupsField = $fields->dataFieldByName('Groups');
|
|
||||||
if($groupsField) $groupsField->setValue($group->ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct($controller, $name, $fields, $validator, $readonly, $dataObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
function forTemplate() {
|
|
||||||
$ret = parent::forTemplate();
|
|
||||||
|
|
||||||
Requirements::css(SAPPHIRE_ADMIN_DIR . '/css/SecurityAdmin.css');
|
|
||||||
Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/MemberTableField.js');
|
|
||||||
Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/MemberTableField_popup.js');
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @package cms
|
|
||||||
* @subpackage security
|
|
||||||
*/
|
|
||||||
class MemberTableField_Item extends ComplexTableField_Item {
|
|
||||||
|
|
||||||
function Actions() {
|
|
||||||
$actions = parent::Actions();
|
|
||||||
|
|
||||||
foreach($actions as $action) {
|
|
||||||
if($action->Name == 'delete') {
|
|
||||||
if($this->parent->getGroup()) {
|
|
||||||
$action->TitleText = _t('MemberTableField.DeleteTitleText',
|
|
||||||
'Delete from this group',
|
|
||||||
PR_MEDIUM,
|
|
||||||
'Delete button hover text'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$action->TitleText = _t('MemberTableField.DeleteTitleTextDatabase',
|
|
||||||
'Delete from database and all groups',
|
|
||||||
PR_MEDIUM,
|
|
||||||
'Delete button hover text'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $actions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -17,9 +17,6 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
|
|||||||
static $subitem_class = 'Member';
|
static $subitem_class = 'Member';
|
||||||
|
|
||||||
static $allowed_actions = array(
|
static $allowed_actions = array(
|
||||||
'autocomplete',
|
|
||||||
'removememberfromgroup',
|
|
||||||
'AddRecordForm',
|
|
||||||
'EditForm',
|
'EditForm',
|
||||||
'MemberImportForm',
|
'MemberImportForm',
|
||||||
'memberimport',
|
'memberimport',
|
||||||
@ -223,51 +220,6 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
|
|||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function AddRecordForm() {
|
|
||||||
$m = Object::create('MemberTableField',
|
|
||||||
$this,
|
|
||||||
"Members",
|
|
||||||
$this->currentPageID()
|
|
||||||
);
|
|
||||||
return $m->AddRecordForm();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ajax autocompletion
|
|
||||||
*/
|
|
||||||
public function autocomplete() {
|
|
||||||
$fieldName = $this->urlParams['ID'];
|
|
||||||
$fieldVal = $_REQUEST[$fieldName];
|
|
||||||
$result = '';
|
|
||||||
$uidField = Member::get_unique_identifier_field();
|
|
||||||
|
|
||||||
// Make sure we only autocomplete on keys that actually exist, and that we don't autocomplete on password
|
|
||||||
if(!singleton($this->stat('subitem_class'))->hasDatabaseField($fieldName) || $fieldName == 'Password') return;
|
|
||||||
|
|
||||||
$matches = DataObject::get($this->stat('subitem_class'),"\"$fieldName\" LIKE '" . Convert::raw2sql($fieldVal) . "%'");
|
|
||||||
if($matches) {
|
|
||||||
$result .= "<ul>";
|
|
||||||
foreach($matches as $match) {
|
|
||||||
// If the current user doesnt have permissions on the target user,
|
|
||||||
// he's not allowed to add it to a group either: Don't include it in the suggestions.
|
|
||||||
if(!$match->canView() || !$match->canEdit()) continue;
|
|
||||||
|
|
||||||
$data = array();
|
|
||||||
foreach($match->summaryFields() as $k => $v) {
|
|
||||||
$data[$k] = $match->$k;
|
|
||||||
}
|
|
||||||
$result .= sprintf(
|
|
||||||
'<li data-fields="%s">%s <span class="informal">(%s)</span></li>',
|
|
||||||
Convert::raw2att(Convert::raw2json($data)),
|
|
||||||
$match->$fieldName,
|
|
||||||
implode(',', array_values($data))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$result .= "</ul>";
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCMSTreeTitle() {
|
function getCMSTreeTitle() {
|
||||||
return _t('SecurityAdmin.SGROUPS', 'Security Groups');
|
return _t('SecurityAdmin.SGROUPS', 'Security Groups');
|
||||||
}
|
}
|
||||||
|
@ -1,347 +0,0 @@
|
|||||||
/**
|
|
||||||
* File: MemberTableField.js
|
|
||||||
*/
|
|
||||||
(function($) {
|
|
||||||
$.entwine('ss', function($){
|
|
||||||
/**
|
|
||||||
* Class: #Permissions .checkbox[value=ADMIN]
|
|
||||||
*
|
|
||||||
* Automatically check and disable all checkboxes if ADMIN permissions are selected.
|
|
||||||
* As they're disabled, any changes won't be submitted (which is intended behaviour),
|
|
||||||
* checking all boxes is purely presentational.
|
|
||||||
*/
|
|
||||||
$('#Permissions .checkbox[value=ADMIN]').entwine({
|
|
||||||
onmatch: function() {
|
|
||||||
this.toggleCheckboxes();
|
|
||||||
|
|
||||||
this._super();
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Function: onclick
|
|
||||||
*/
|
|
||||||
onclick: function(e) {
|
|
||||||
this.toggleCheckboxes();
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Function: toggleCheckboxes
|
|
||||||
*/
|
|
||||||
toggleCheckboxes: function() {
|
|
||||||
var self = this, checkboxes = this.parents('.field:eq(0)').find('.checkbox').not(this);
|
|
||||||
|
|
||||||
if(this.is(':checked')) {
|
|
||||||
checkboxes.each(function() {
|
|
||||||
$(this).data('SecurityAdmin.oldChecked', $(this).attr('checked'));
|
|
||||||
$(this).data('SecurityAdmin.oldDisabled', $(this).attr('disabled'));
|
|
||||||
$(this).attr('disabled', 'disabled');
|
|
||||||
$(this).attr('checked', 'checked');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
checkboxes.each(function() {
|
|
||||||
$(this).attr('checked', $(this).data('SecurityAdmin.oldChecked'));
|
|
||||||
$(this).attr('disabled', $(this).data('SecurityAdmin.oldDisabled'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}(jQuery));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modified 2006-10-05, Ingo Schommer
|
|
||||||
* This is more or less a copy of Member.js, with additions and changes
|
|
||||||
* to match the switch from Member.php to MemberTableField.php all over the UI.
|
|
||||||
* Eventually it will replace Member.js (please remove this message then).
|
|
||||||
*/
|
|
||||||
|
|
||||||
// no confirm message for removal from a group
|
|
||||||
if(typeof(ComplexTableField) != 'undefined') {
|
|
||||||
ComplexTableField.prototype.deleteConfirmMessage = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class: AjaxMemberLookup
|
|
||||||
*
|
|
||||||
* Auto-lookup on ajax fields
|
|
||||||
*/
|
|
||||||
AjaxMemberLookup = {
|
|
||||||
initialise : function() {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
div.id = this.id + '_ac';
|
|
||||||
div.className = 'autocomplete';
|
|
||||||
this.parentNode.appendChild(div);
|
|
||||||
if(this.id) {
|
|
||||||
new Ajax.Autocompleter(this.id, div.id, 'admin/security/autocomplete/' + this.name, {
|
|
||||||
afterUpdateElement : this.afterAutocomplete.bind(this)
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
afterAutocomplete : function(field, selectedItem) {
|
|
||||||
var items = jQuery(selectedItem).data('fields'), form = jQuery(selectedItem).parents('form:first');
|
|
||||||
for(name in items) {
|
|
||||||
jQuery(form).find('input[name='+name+']').val(items[name]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class: MemberTableField
|
|
||||||
*/
|
|
||||||
MemberTableField = Class.create();
|
|
||||||
MemberTableField.applyTo('.cms-edit-form div.MemberTableField');
|
|
||||||
MemberTableField.prototype = {
|
|
||||||
|
|
||||||
initialize: function() {
|
|
||||||
Behaviour.register({
|
|
||||||
'.cms-edit-form div.MemberFilter input' : {
|
|
||||||
onkeypress : this.prepareSearch.bind(this)
|
|
||||||
},
|
|
||||||
|
|
||||||
'.cms-edit-form div.MemberTableField table.data tr.addtogrouprow input' : {
|
|
||||||
onkeypress : this.prepareAddToGroup.bind(this)
|
|
||||||
},
|
|
||||||
|
|
||||||
'.cms-edit-form div.MemberTableField table.data tr.addtogrouprow #Form_AddRecordForm_action_addtogroup' : {
|
|
||||||
onclick : this.prepareAddToGroup.bind(this)
|
|
||||||
},
|
|
||||||
|
|
||||||
'.cms-edit-form div.MemberTableField table.data tr.addtogrouprow td.actions input' : {
|
|
||||||
initialise: function() {
|
|
||||||
data = this.parentNode.parentNode.getElementsByTagName('input');
|
|
||||||
var i,item,error = [];
|
|
||||||
for(i=0;item=data[i];i++) {
|
|
||||||
item.originalSerialized = Form.Element.serialize(item);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onclick : this.addToGroup.bind(this)
|
|
||||||
},
|
|
||||||
|
|
||||||
//'.cms-edit-form div.MemberTableField input' : AjaxMemberLookup,
|
|
||||||
|
|
||||||
'.cms-edit-form' : {
|
|
||||||
changeDetection_fieldsToIgnore : {
|
|
||||||
'ctf[start]' : true,
|
|
||||||
'ctf[ID]' : true,
|
|
||||||
'MemberOrderByField' : true,
|
|
||||||
'MemberOrderByOrder' : true,
|
|
||||||
'MemberGroup' : true,
|
|
||||||
'MemberFilterButton' : true,
|
|
||||||
'MemberFieldName' : true,
|
|
||||||
'MemberDontShowPassword' : true,
|
|
||||||
'MemberSearch' : true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// prevent submission of wrong form-button (MemberFilterButton)
|
|
||||||
prepareAddToGroup: function(e) {
|
|
||||||
// IE6 doesnt send an event-object with onkeypress
|
|
||||||
var event = (e) ? e : window.event;
|
|
||||||
var keyCode = (event.keyCode) ? event.keyCode : event.which;
|
|
||||||
if(keyCode == Event.KEY_RETURN) {
|
|
||||||
var el = Event.element(event);
|
|
||||||
this.addToGroup(event);
|
|
||||||
Event.stop(event);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// prevent submission of wrong form-button (MemberFilterButton)
|
|
||||||
prepareSearch: function(e) {
|
|
||||||
// IE6 doesnt send an event-object with onkeypress
|
|
||||||
var event = (e) ? e : window.event;
|
|
||||||
var keyCode = (event.keyCode) ? event.keyCode : event.which;
|
|
||||||
|
|
||||||
if(keyCode == Event.KEY_RETURN) {
|
|
||||||
var el = Event.element(event);
|
|
||||||
$('MemberFilterButton').onclick(event);
|
|
||||||
Event.stop(event);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
addToGroup: function(e) {
|
|
||||||
// only submit parts of the form
|
|
||||||
var data = this.parentNode.parentNode.getElementsByTagName('input');
|
|
||||||
var i,item,error = [];
|
|
||||||
var form = Event.findElement(e,"form");
|
|
||||||
|
|
||||||
for(i=0;item=data[i];i++) {
|
|
||||||
if(item.name == 'Email' && !item.value) error[error.length] = "Email";
|
|
||||||
if(item.name == 'Password' && !item.value) error[error.length] = "Password";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(error.length > 0) {
|
|
||||||
alert('Please enter a ' + error.join(' and a ') + ' to add a member.');
|
|
||||||
} else {
|
|
||||||
updateURL = "";
|
|
||||||
updateURL += Event.findElement(e,"form").action;
|
|
||||||
// we can't set "fieldName" as a HiddenField because there might be multiple ComplexTableFields in a single EditForm-container
|
|
||||||
updateURL += "?fieldName="+$('MemberFieldName').value;
|
|
||||||
updateURL += "&action_callfieldmethod&methodName=addtogroup";
|
|
||||||
|
|
||||||
ajaxSubmitFieldSet(updateURL, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
initialise : function() {
|
|
||||||
this.headerMap = [];
|
|
||||||
|
|
||||||
var i, item, headers = this.getElementsByTagName('thead')[0].getElementsByTagName('tr')[0].getElementsByTagName('td');
|
|
||||||
for(i=0;item=headers[i];i++) {
|
|
||||||
this.headerMap[i] = item.className;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setRecordDetails : function(id, details, groupID) {
|
|
||||||
var row = document.getElementById('member-' + id);
|
|
||||||
if(row) {
|
|
||||||
var i, item, cells = row.getElementsByTagName('td');
|
|
||||||
for(i=0;item=cells[i];i++) {
|
|
||||||
if(details[this.headerMap[i]]) {
|
|
||||||
item.innerHTML = details[this.headerMap[i]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.createRecord(id, details, groupID);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
createRecord : function (id, details, groupId) {
|
|
||||||
var row = document.createElement('tr');
|
|
||||||
row.id = 'member-' + id;
|
|
||||||
var i, cell, cellField;
|
|
||||||
for(i=0;cellField=this.headerMap[i];i++) {
|
|
||||||
cell = document.createElement('td')
|
|
||||||
if(details[cellField]) {
|
|
||||||
cell.innerHTML = details[cellField];
|
|
||||||
}
|
|
||||||
row.appendChild(cell);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the delete icon
|
|
||||||
if(typeof groupId == 'undefined')
|
|
||||||
var groupId = $('Form_EditForm').elements.ID.value;
|
|
||||||
cell = document.createElement('td')
|
|
||||||
cell.innerHTML = '<a class="deletelink" href="admin/security/removememberfromgroup/' + groupId + '/' + id + '"><img src="sapphire/images/delete.gif" alt="delete" /></a>';
|
|
||||||
cell.getElementsByTagName('0');
|
|
||||||
row.appendChild(cell);
|
|
||||||
|
|
||||||
var tbody = this.getElementsByTagName('tbody')[0];
|
|
||||||
var addRow = document.getElementsByClassName('addrow',tbody)[0];
|
|
||||||
if(addRow) tbody.insertBefore(row, addRow);
|
|
||||||
else tbody.appendChild(row);
|
|
||||||
Behaviour.apply(row, true);
|
|
||||||
},
|
|
||||||
clearAddForm : function() {
|
|
||||||
var tbody = this.getElementsByTagName('tbody')[0];
|
|
||||||
var addRow = document.getElementsByClassName('addrow',tbody)[0];
|
|
||||||
if(addRow) {
|
|
||||||
var i,field,fields = addRow.getElementsByTagName('input');
|
|
||||||
for(i=0;field=fields[i];i++) {
|
|
||||||
if(field.type != 'hidden' && field.type != 'submit') field.value = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
removeMember : function(memberID) {
|
|
||||||
var record;
|
|
||||||
if(record = $('member-' + memberID)) {
|
|
||||||
record.parentNode.removeChild(record);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class: MemberFilterButton
|
|
||||||
*/
|
|
||||||
MemberFilterButton = Class.create();
|
|
||||||
MemberFilterButton.applyTo('#MemberFilterButton');
|
|
||||||
MemberFilterButton.prototype = {
|
|
||||||
initialize: function() {
|
|
||||||
this.inputFields = new Array();
|
|
||||||
|
|
||||||
var childNodes = this.parentNode.parentNode.getElementsByTagName('input');
|
|
||||||
|
|
||||||
for( var index = 0; index < childNodes.length; index++ ) {
|
|
||||||
if( childNodes[index].tagName ) {
|
|
||||||
childNodes[index].resetChanged = function() { return false; }
|
|
||||||
childNodes[index].isChanged = function() { return false; }
|
|
||||||
this.inputFields.push( childNodes[index] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
childNodes = this.parentNode.getElementsByTagName('select');
|
|
||||||
|
|
||||||
for( var index = 0; index < childNodes.length; index++ ) {
|
|
||||||
if( childNodes[index].tagName ) {
|
|
||||||
childNodes[index].resetChanged = function() { return false; }
|
|
||||||
childNodes[index].field_changed = function() { return false; }
|
|
||||||
this.inputFields.push( childNodes[index] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
isChanged: function() {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
onclick: function(e) {
|
|
||||||
if(!$('ctf-ID') || !$('MemberFieldName')) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
var form = Event.findElement(e,"form");
|
|
||||||
var fieldName = $('MemberFieldName').value;
|
|
||||||
var fieldID = form.id + '_' + fieldName;
|
|
||||||
|
|
||||||
var updateURL = form.action + '/field/' + fieldName + '?ajax=1';
|
|
||||||
for( var index = 0; index < this.inputFields.length; index++ ) {
|
|
||||||
if( this.inputFields[index].tagName ) {
|
|
||||||
updateURL += '&' + this.inputFields[index].name + '=' + encodeURIComponent( this.inputFields[index].value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jQuery($(fieldID)).get(updateURL, null, function() {Behaviour.apply($(fieldID), true);});
|
|
||||||
} catch(er) {
|
|
||||||
errorMessage('Error searching');
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// has to be external from initialize() because otherwise request will double on each reload - WTF
|
|
||||||
Behaviour.register({
|
|
||||||
'.cms-edit-form div.MemberTableField table.data input.text' : AjaxMemberLookup
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Post the given fields to the given url
|
|
||||||
*/
|
|
||||||
function ajaxSubmitFieldSet(href, fieldSet, extraData) {
|
|
||||||
// Build data
|
|
||||||
var i,field,data = "ajax=1";
|
|
||||||
for(i=0;field=fieldSet[i];i++) {
|
|
||||||
data += '&' + Form.Element.serialize(field);
|
|
||||||
}
|
|
||||||
if(extraData){
|
|
||||||
data += '&'+extraData;
|
|
||||||
}
|
|
||||||
// Send request
|
|
||||||
jQuery.ajax({
|
|
||||||
'url': href,
|
|
||||||
'method' : 'post',
|
|
||||||
'data' : data,
|
|
||||||
'success' : function(response) {
|
|
||||||
eval(response);
|
|
||||||
},
|
|
||||||
'error' : function(response) {
|
|
||||||
alert(response.responseText);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
/**
|
|
||||||
* File: MemberTableField_popup.js
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class: MemberTableFieldPopupForm
|
|
||||||
*/
|
|
||||||
MemberTableFieldPopupForm = Class.extend("ComplexTableFieldPopupForm");
|
|
||||||
MemberTableFieldPopupForm.prototype = {
|
|
||||||
initialize: function() {
|
|
||||||
this.ComplexTableFieldPopupForm.initialize();
|
|
||||||
|
|
||||||
Behaviour.register('MemberTableFieldPopupForm',{
|
|
||||||
"div.MemberTableField_Popup .Actions input.action": {
|
|
||||||
onclick: this.submitForm.bind(this)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MemberTableFieldPopupForm.applyTo('div.MemberTableField_Popup .Actions');
|
|
@ -30,42 +30,47 @@
|
|||||||
$(this).bind('load', refreshAfterImport);
|
$(this).bind('load', refreshAfterImport);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete selected folders through "batch actions" tab.
|
|
||||||
*/
|
|
||||||
$(document).ready(function() {
|
|
||||||
$('#Form_BatchActionsForm').entwine('ss').register(
|
|
||||||
// TODO Hardcoding of base URL
|
|
||||||
'admin/security/batchactions/delete',
|
|
||||||
function(ids) {
|
|
||||||
var confirmed = confirm(
|
|
||||||
ss.i18n.sprintf(
|
|
||||||
ss.i18n._t('SecurityAdmin.BATCHACTIONSDELETECONFIRM'),
|
|
||||||
ids.length
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return (confirmed) ? ids : false;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$.entwine('ss', function($){
|
$.entwine('ss', function($){
|
||||||
/**
|
/**
|
||||||
* Class: .cms-edit-form .Actions #Form_EditForm_action_addmember
|
* Class: #Permissions .checkbox[value=ADMIN]
|
||||||
|
*
|
||||||
|
* Automatically check and disable all checkboxes if ADMIN permissions are selected.
|
||||||
|
* As they're disabled, any changes won't be submitted (which is intended behaviour),
|
||||||
|
* checking all boxes is purely presentational.
|
||||||
*/
|
*/
|
||||||
$('.cms-edit-form .Actions #Form_EditForm_action_addmember').entwine({
|
$('#Permissions .checkbox[value=ADMIN]').entwine({
|
||||||
// Function: onclick
|
onmatch: function() {
|
||||||
|
this.toggleCheckboxes();
|
||||||
|
|
||||||
|
this._super();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Function: onclick
|
||||||
|
*/
|
||||||
onclick: function(e) {
|
onclick: function(e) {
|
||||||
// CAUTION: Assumes that a MemberTableField-instance is present as an editing form
|
this.toggleCheckboxes();
|
||||||
var t = $('#Form_EditForm_Members');
|
},
|
||||||
t[0].openPopup(
|
/**
|
||||||
null,
|
* Function: toggleCheckboxes
|
||||||
$('base').attr('href') + t.find('a.addlink').attr('href'),
|
*/
|
||||||
t.find('table')[0]
|
toggleCheckboxes: function() {
|
||||||
);
|
var self = this, checkboxes = this.parents('.field:eq(0)').find('.checkbox').not(this);
|
||||||
return false;
|
|
||||||
|
if(this.is(':checked')) {
|
||||||
|
checkboxes.each(function() {
|
||||||
|
$(this).data('SecurityAdmin.oldChecked', $(this).attr('checked'));
|
||||||
|
$(this).data('SecurityAdmin.oldDisabled', $(this).attr('disabled'));
|
||||||
|
$(this).attr('disabled', 'disabled');
|
||||||
|
$(this).attr('checked', 'checked');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
checkboxes.each(function() {
|
||||||
|
$(this).attr('checked', $(this).data('SecurityAdmin.oldChecked'));
|
||||||
|
$(this).attr('disabled', $(this).data('SecurityAdmin.oldDisabled'));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
<div id="$id" class="$CSSClasses $extraClass field" href="$CurrentLink">
|
|
||||||
<div class="MemberFilter filterBox">
|
|
||||||
$SearchForm
|
|
||||||
</div>
|
|
||||||
<div id="MemberList">
|
|
||||||
<% if Markable %>
|
|
||||||
<% include TableListField_SelectOptions %>
|
|
||||||
<% end_if %>
|
|
||||||
<% include TableListField_PageControls %>
|
|
||||||
<table class="data">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<% if Markable %><th width="18"> </th><% end_if %>
|
|
||||||
<% control Headings %>
|
|
||||||
<th class="$Name">$Title</th>
|
|
||||||
<% end_control %>
|
|
||||||
<% if Can(show) %><th width="18"> </th><% end_if %>
|
|
||||||
<% if Can(edit) %><th width="18"> </th><% end_if %>
|
|
||||||
<% if Can(delete) %><th width="18"> </th><% end_if %>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tfoot>
|
|
||||||
<% if Can(inlineadd) %>
|
|
||||||
<tr class="addtogrouprow">
|
|
||||||
<% if Markable %><td width="18"> </dh><% end_if %>
|
|
||||||
$AddRecordForm.CellFields
|
|
||||||
<td class="actions" colspan="3">$AddRecordForm.CellActions</td>
|
|
||||||
</tr>
|
|
||||||
<% end_if %>
|
|
||||||
<tr style="display: none;">
|
|
||||||
<% if Markable %><td width="18"> </td><% end_if %>
|
|
||||||
<td colspan="$ItemCount">
|
|
||||||
<input type="hidden" id="{$id}_PopupHeight" value="$PopupHeight" disabled="disabled"/>
|
|
||||||
<input type="hidden" id="{$id}_PopupWidth" value="$PopupWidth" disabled="disabled"/>
|
|
||||||
<a class="popuplink addlink" href="$AddLink" alt="add"><img src="sapphire/images/add.gif" alt="add" /></a><a class="popuplink addlink" href="$AddLink" alt="add"><% _t('ADDNEW','Add new',50,'Followed by a member type') %> $Title</a>
|
|
||||||
</td>
|
|
||||||
<% if Can(show) %><td width="18"> </td><% end_if %>
|
|
||||||
<% if Can(edit) %><td width="18"> </td><% end_if %>
|
|
||||||
<% if Can(delete) %><td width="18"> </td><% end_if %>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
<tbody>
|
|
||||||
<% if Items %>
|
|
||||||
<% control Items %>
|
|
||||||
<% include TableListField_Item %>
|
|
||||||
<% end_control %>
|
|
||||||
<% else %>
|
|
||||||
<tr class="notfound">
|
|
||||||
<% if Markable %><th width="18"> </th><% end_if %>
|
|
||||||
<td colspan="$Headings.Count"><i><% _t('NOITEMSFOUND', 'No items found') %></i></td>
|
|
||||||
<% control Actions %><td width="18"> </td><% end_control %>
|
|
||||||
</tr>
|
|
||||||
<% end_if %>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="utility">
|
|
||||||
<% control Utility %>
|
|
||||||
<span class="item"><a href="$Link" target="_blank">$Title</a></span>
|
|
||||||
<% end_control %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,139 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* @package cms
|
|
||||||
* @subpackage tests
|
|
||||||
*/
|
|
||||||
|
|
||||||
class MemberTableFieldTest extends FunctionalTest {
|
|
||||||
|
|
||||||
static $fixture_file = 'sapphire/admin/tests/MemberTableFieldTest.yml';
|
|
||||||
|
|
||||||
|
|
||||||
function testLimitsToMembersInGroup() {
|
|
||||||
$member1 = $this->objFromFixture('Member', 'member1');
|
|
||||||
$member2 = $this->objFromFixture('Member', 'member2');
|
|
||||||
$member3 = $this->objFromFixture('Member', 'member3');
|
|
||||||
$group1 = $this->objFromFixture('Group', 'group1');
|
|
||||||
|
|
||||||
$tf = new MemberTableField(
|
|
||||||
$this,
|
|
||||||
"Members",
|
|
||||||
$group1
|
|
||||||
);
|
|
||||||
$members = $tf->sourceItems();
|
|
||||||
|
|
||||||
$this->assertContains($member1->ID, $members->column('ID'),
|
|
||||||
'Members in the associated group are listed'
|
|
||||||
);
|
|
||||||
$this->assertContains($member2->ID, $members->column('ID'),
|
|
||||||
'Members in children groups are listed as well'
|
|
||||||
);
|
|
||||||
$this->assertNotContains($member3->ID, $members->column('ID'),
|
|
||||||
'Members in other groups are filtered out'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testShowsAllMembersWithoutGroupParameter() {
|
|
||||||
$member1 = $this->objFromFixture('Member', 'member1');
|
|
||||||
$member2 = $this->objFromFixture('Member', 'member2');
|
|
||||||
$member3 = $this->objFromFixture('Member', 'member3');
|
|
||||||
$group1 = $this->objFromFixture('Group', 'group1');
|
|
||||||
|
|
||||||
$tf = new MemberTableField(
|
|
||||||
$this,
|
|
||||||
"Members"
|
|
||||||
// no group assignment
|
|
||||||
);
|
|
||||||
$members = $tf->sourceItems();
|
|
||||||
|
|
||||||
$this->assertContains($member1->ID, $members->column('ID'),
|
|
||||||
'Members in the associated group are listed'
|
|
||||||
);
|
|
||||||
$this->assertContains($member2->ID, $members->column('ID'),
|
|
||||||
'Members in children groups are listed as well'
|
|
||||||
);
|
|
||||||
$this->assertContains($member3->ID, $members->column('ID'),
|
|
||||||
'Members in other groups are listed'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testDeleteWithGroupOnlyDeletesRelation() {
|
|
||||||
$member1 = $this->objFromFixture('Member', 'member1');
|
|
||||||
$group1 = $this->objFromFixture('Group', 'group1');
|
|
||||||
|
|
||||||
$response = $this->get('MemberTableFieldTest_Controller');
|
|
||||||
$token = SecurityToken::inst();
|
|
||||||
$url = sprintf('MemberTableFieldTest_Controller/Form/field/Members/item/%d/delete/?usetestmanifest=1', $member1->ID);
|
|
||||||
$url = $token->addToUrl($url);
|
|
||||||
$response = $this->get($url);
|
|
||||||
|
|
||||||
$group1->flushCache();
|
|
||||||
|
|
||||||
$this->assertNotContains($member1->ID, $group1->Members()->column('ID'),
|
|
||||||
'Member relation to group is removed'
|
|
||||||
);
|
|
||||||
$this->assertType(
|
|
||||||
'DataObject',
|
|
||||||
DataObject::get_by_id('Member', $member1->ID),
|
|
||||||
'Member record still exists'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testDeleteWithoutGroupDeletesFromDatabase() {
|
|
||||||
$member1 = $this->objFromFixture('Member', 'member1');
|
|
||||||
$member1ID = $member1->ID;
|
|
||||||
$group1 = $this->objFromFixture('Group', 'group1');
|
|
||||||
|
|
||||||
$response = $this->get('MemberTableFieldTest_Controller');
|
|
||||||
$token = SecurityToken::inst();
|
|
||||||
$url = sprintf('MemberTableFieldTest_Controller/FormNoGroup/field/Members/item/%d/delete/?usetestmanifest=1', $member1->ID);
|
|
||||||
$url = $token->addToUrl($url);
|
|
||||||
$response = $this->get($url);
|
|
||||||
|
|
||||||
$group1->flushCache();
|
|
||||||
|
|
||||||
$this->assertNotContains($member1->ID, $group1->Members()->column('ID'),
|
|
||||||
'Member relation to group is removed'
|
|
||||||
);
|
|
||||||
DataObject::flush_and_destroy_cache();
|
|
||||||
$this->assertFalse(
|
|
||||||
DataObject::get_by_id('Member', $member1ID),
|
|
||||||
'Member record is removed from database'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MemberTableFieldTest_Controller extends Controller implements TestOnly {
|
|
||||||
|
|
||||||
protected $template = 'BlankPage';
|
|
||||||
|
|
||||||
function Link($action = null) {
|
|
||||||
return Controller::join_links('MemberTableFieldTest_Controller', $action);
|
|
||||||
}
|
|
||||||
|
|
||||||
function Form() {
|
|
||||||
$group1 = DataObject::get_one('Group', '"Code" = \'group1\'');
|
|
||||||
return new Form(
|
|
||||||
$this,
|
|
||||||
'FormNoGroup',
|
|
||||||
new FieldList(new MemberTableField($this, "Members", $group1)),
|
|
||||||
new FieldList(new FormAction('submit'))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function FormNoGroup() {
|
|
||||||
$tf = new MemberTableField(
|
|
||||||
$this,
|
|
||||||
"Members"
|
|
||||||
// no group
|
|
||||||
);
|
|
||||||
|
|
||||||
return new Form(
|
|
||||||
$this,
|
|
||||||
'FormNoGroup',
|
|
||||||
new FieldList(new MemberTableField($this, "Members")),
|
|
||||||
new FieldList(new FormAction('submit'))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
Group:
|
|
||||||
admin:
|
|
||||||
Title: Administrators
|
|
||||||
Code: admin
|
|
||||||
group1:
|
|
||||||
Title: Group1
|
|
||||||
Code: group1
|
|
||||||
group1_child:
|
|
||||||
Title: Group1 Child
|
|
||||||
Parent: =>Group.group1
|
|
||||||
Code: group1_child
|
|
||||||
group2:
|
|
||||||
Title: Group2
|
|
||||||
Code: group2
|
|
||||||
Member:
|
|
||||||
admin:
|
|
||||||
Email: admin@example.com
|
|
||||||
Groups: =>Group.admin
|
|
||||||
member1:
|
|
||||||
Email: member1@test.com
|
|
||||||
Groups: =>Group.group1
|
|
||||||
member2:
|
|
||||||
Email: member2@test.com
|
|
||||||
Groups: =>Group.group1_child
|
|
||||||
member3:
|
|
||||||
Email: member3@test.com
|
|
||||||
Groups: =>Group.group2
|
|
||||||
Permission:
|
|
||||||
admin:
|
|
||||||
Code: ADMIN
|
|
||||||
GroupID: =>Group.admin
|
|
@ -182,3 +182,4 @@ BreadcrumbsTemplate.ss from cms/template to your theme or application.
|
|||||||
* `DataObjectLog`: There is no replacement for this.
|
* `DataObjectLog`: There is no replacement for this.
|
||||||
* `GeoIP`: Moved to separate ["geoip" module](https://github.com/silverstripe-labs/silverstripe-geoip)
|
* `GeoIP`: Moved to separate ["geoip" module](https://github.com/silverstripe-labs/silverstripe-geoip)
|
||||||
* `NZGovtPasswordValidator`: Moved to ["securityextras" module](https://github.com/silverstripe-labs/silverstripe-securityextras)
|
* `NZGovtPasswordValidator`: Moved to ["securityextras" module](https://github.com/silverstripe-labs/silverstripe-securityextras)
|
||||||
|
* `MemberTableField`: Use GridField with GridFieldConfig_RelationEditor instead
|
Loading…
x
Reference in New Issue
Block a user