2007-07-19 12:40:05 +02:00
< ? 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 .
2007-09-14 21:39:59 +02:00
*
2007-07-19 12:40:05 +02:00
* In contrast to the original implementation , the URL - parameters " ParentClass " and " ParentID " are used
* to specify " Group " ( hardcoded ) and the GroupID - relation .
*
2009-02-04 21:36:23 +01:00
* @ todo write a better description about what this field does .
*
2007-07-19 12:40:05 +02:00
* Returns either :
* - provided members
* - members of a provided group
* - all members
* - members based on a search - query
2008-02-25 03:10:37 +01:00
* @ package cms
* @ subpackage security
2007-07-19 12:40:05 +02:00
*/
class MemberTableField extends ComplexTableField {
2008-02-25 03:10:37 +01:00
2007-07-19 12:40:05 +02:00
protected $members ;
2008-02-25 03:10:37 +01:00
2007-07-19 12:40:05 +02:00
protected $hidePassword ;
2008-02-25 03:10:37 +01:00
2007-07-19 12:40:05 +02:00
protected $detailFormValidator ;
2008-02-25 03:10:37 +01:00
2007-07-19 12:40:05 +02:00
protected $group ;
2007-09-14 21:39:59 +02:00
2009-02-04 21:36:23 +01:00
protected $template = 'MemberTableField' ;
2007-09-14 21:39:59 +02:00
2008-02-25 03:10:37 +01:00
public $popupClass = 'MemberTableField_Popup' ;
2009-02-04 21:36:23 +01:00
static $data_class = 'Member' ;
2009-03-04 04:35:29 +01:00
/**
* Set the page size for this table .
* @ var int
*/
public static $page_size = 20 ;
2009-02-10 04:27:12 +01:00
/**
* @ deprecated 2.4 . See { @ link MemberTableField -> addPermissions ()}
*/
private static $addedPermissions = array ();
2009-02-04 21:36:23 +01:00
/**
* @ deprecated 2.4 : See { @ link MemberTableField -> addMembershipFields ()}
*/
2007-07-19 12:40:05 +02:00
private static $addedFields = array ();
2007-09-15 22:10:43 +02:00
2009-02-04 21:36:23 +01:00
/**
* @ deprecated 2.4 : See { @ link MemberTableField -> addMembershipFields ()}
*/
private static $addedCsvFields = array ();
2009-02-10 04:27:12 +01:00
/**
* @ deprecated 2.4 . Set permissions using setPermissions ( Array ) on
* the MemberTableField object .
*/
public static function addPermissions ( $addingPermissionList ) {
trigger_error ( 'MemberTableField::addPermissions() is deprecated. Please set permissions using setPermissions(Array) on the MemberTableField object.' , E_USER_NOTICE );
self :: $addedPermissions = $addingPermissionList ;
}
2009-02-04 21:36:23 +01:00
/**
* @ deprecated 2.4 : Please use a DataObjectDecorator , implementing updateSummaryFields
* to alter the table overview fields instead .
*/
2009-02-03 04:22:20 +01:00
public static function addMembershipFields ( $addingFieldList , $addingCsvFieldList = null ) {
2009-02-04 21:36:23 +01:00
trigger_error ( 'MemberTableField::addMembershipFields() is deprecated. Please implement updateSummaryFields() on a Member decorator instead.' , E_USER_NOTICE );
2007-07-19 12:40:05 +02:00
self :: $addedFields = $addingFieldList ;
$addingCsvFieldList == null ? self :: $addedCsvFields = $addingFieldList : self :: $addedCsvFields = $addingCsvFieldList ;
}
2007-09-15 22:10:43 +02:00
2009-02-04 21:36:23 +01:00
/**
* 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 DataObjectSet $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 , $members = null , $hidePassword = true ) {
$sourceClass = self :: $data_class ;
$SNG_member = singleton ( $sourceClass );
$fieldList = $SNG_member -> summaryFields ();
$memberDbFields = $SNG_member -> db ();
$csvFieldList = array ();
foreach ( $memberDbFields as $field => $dbFieldType ) {
$csvFieldList [ $field ] = $field ;
}
2007-07-19 12:40:05 +02:00
if ( $group ) {
if ( is_object ( $group )) {
$this -> group = $group ;
2009-02-03 04:22:20 +01:00
} elseif ( is_numeric ( $group )) {
$this -> group = DataObject :: get_by_id ( 'Group' , $group );
2007-09-14 21:39:59 +02:00
}
2009-02-04 21:36:23 +01:00
} elseif ( is_numeric ( $_REQUEST [ 'ctf' ][ $this -> Name ()][ 'ID' ])) {
$this -> group = DataObject :: get_by_id ( 'Group' , $_REQUEST [ 'ctf' ][ $this -> Name ()][ 'ID' ]);
2009-02-03 04:22:20 +01:00
}
2007-07-19 12:40:05 +02:00
2009-02-03 04:22:20 +01:00
foreach ( self :: $addedFields as $key => $value ) {
2007-07-19 12:40:05 +02:00
$fieldList [ $key ] = $value ;
}
2007-09-15 22:10:43 +02:00
2007-07-19 12:40:05 +02:00
if ( ! $hidePassword ) {
2008-02-25 03:10:37 +01:00
$fieldList [ " SetPassword " ] = " Password " ;
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:39:59 +02:00
2009-02-04 21:36:23 +01:00
$this -> hidePassword = $hidePassword ;
// @todo shouldn't this use $this->group? It's unclear exactly
// what group it should be customising the custom Member set with.
2007-07-19 12:40:05 +02:00
if ( $members ) {
2009-02-04 21:36:23 +01:00
$this -> setCustomSourceItems ( $this -> memberListWithGroupID ( $members , $group ));
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:39:59 +02:00
2008-10-03 18:33:37 +02:00
parent :: __construct ( $controller , $name , $sourceClass , $fieldList );
2007-09-14 21:39:59 +02:00
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@63175 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-28 15:12:20 +02:00
Requirements :: javascript ( CMS_DIR . '/javascript/MemberTableField.js' );
2009-02-04 21:36:23 +01:00
Requirements :: javascript ( CMS_DIR . '/javascript/MemberTableField_popup.js' );
2008-10-08 03:00:08 +02:00
2008-03-10 22:28:15 +01:00
$SQL_search = isset ( $_REQUEST [ 'MemberSearch' ]) ? Convert :: raw2sql ( $_REQUEST [ 'MemberSearch' ]) : null ;
2007-07-19 12:40:05 +02:00
if ( ! empty ( $_REQUEST [ 'MemberSearch' ])) {
2008-03-10 22:28:15 +01:00
$searchFilters = array ();
2008-08-27 06:58:34 +02:00
foreach ( $SNG_member -> searchableFields () as $fieldName => $fieldSpec ) {
2009-02-04 21:36:23 +01:00
if ( strpos ( $fieldName , '.' ) === false ) $searchFilters [] = " \" $fieldName\ " LIKE '%{$SQL_search}%' " ;
2008-03-10 22:28:15 +01:00
}
2008-11-04 00:30:16 +01:00
$this -> sourceFilter [] = '(' . implode ( ' OR ' , $searchFilters ) . ')' ;
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:39:59 +02:00
2008-11-23 01:31:13 +01:00
$this -> sourceJoin = " INNER JOIN \" Group_Members \" ON \" MemberID \" = \" Member \" . \" ID \" " ;
2009-02-03 04:46:15 +01:00
$this -> setFieldListCsv ( $csvFieldList );
2009-03-04 04:35:29 +01:00
$this -> setPageSize ( $this -> stat ( 'page_size' ));
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
function sourceID () {
return $this -> group -> ID ;
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
function AddLink () {
2008-10-08 02:07:53 +02:00
return $this -> Link () . '/add' ;
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
function SearchForm () {
$searchFields = new FieldGroup (
2008-02-25 03:10:37 +01:00
new TextField ( 'MemberSearch' , _t ( 'MemberTableField.SEARCH' , 'Search' )),
2009-02-04 21:36:23 +01:00
new HiddenField ( 'ctf[ID]' , '' , $this -> group -> ID ),
2009-02-03 04:22:20 +01:00
new HiddenField ( 'MemberFieldName' , '' , $this -> name ),
new HiddenField ( 'MemberDontShowPassword' , '' , $this -> hidePassword )
2007-07-19 12:40:05 +02:00
);
2007-09-14 21:39:59 +02:00
2008-02-25 03:10:37 +01:00
$actionFields = new LiteralField ( 'MemberFilterButton' , '<input type="submit" class="action" name="MemberFilterButton" value="' . _t ( 'MemberTableField.FILTER' , 'Filter' ) . '" id="MemberFilterButton"/>' );
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
$fieldContainer = new FieldGroup (
2009-02-03 04:22:20 +01:00
$searchFields ,
$actionFields
2007-07-19 12:40:05 +02:00
);
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
return $fieldContainer -> FieldHolder ();
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
/**
* Add existing member to group rather than creating a new member
*/
function addtogroup () {
$data = $_REQUEST ;
unset ( $data [ 'ID' ]);
2009-01-05 07:17:59 +01:00
$ctfID = isset ( $data [ 'ctf' ]) ? $data [ 'ctf' ][ 'ID' ] : null ;
2007-07-19 12:40:05 +02:00
2009-01-05 07:17:59 +01:00
if ( ! is_numeric ( $ctfID )) {
FormResponse :: status_messsage ( _t ( 'MemberTableField.ADDINGFIELD' , 'Adding failed' ), 'bad' );
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:39:59 +02:00
2009-02-04 21:36:23 +01:00
$className = self :: $data_class ;
2007-07-19 12:40:05 +02:00
$record = new $className ();
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
$record -> update ( $data );
2008-04-26 08:28:33 +02:00
$valid = $record -> validate ();
2009-01-05 07:17:59 +01:00
2008-04-26 08:28:33 +02:00
if ( $valid -> valid ()) {
$record -> write ();
2009-01-05 07:17:59 +01:00
$record -> Groups () -> add ( $ctfID );
2007-09-15 22:10:43 +02:00
2008-04-26 08:28:33 +02:00
$this -> sourceItems ();
2007-07-19 12:40:05 +02:00
2008-04-26 08:28:33 +02:00
// 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 );
2009-02-04 22:13:04 +01:00
FormResponse :: status_message (
_t (
'MemberTableField.ADDEDTOGROUP' , 'Added member to group'
),
'good'
);
2008-04-26 08:28:33 +02:00
} else {
2009-02-04 22:13:04 +01:00
$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' );
2008-04-26 08:28:33 +02:00
}
2007-07-19 12:40:05 +02:00
return FormResponse :: respond ();
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
/**
* Custom delete implementation :
* Remove member from group rather than from the database
*/
function delete () {
2008-02-25 03:10:37 +01:00
$groupID = Convert :: raw2sql ( $_REQUEST [ 'ctf' ][ 'ID' ]);
$memberID = Convert :: raw2sql ( $_REQUEST [ 'ctf' ][ 'childID' ]);
2007-07-19 12:40:05 +02:00
if ( is_numeric ( $groupID ) && is_numeric ( $memberID )) {
$member = DataObject :: get_by_id ( 'Member' , $memberID );
$member -> Groups () -> remove ( $groupID );
} else {
user_error ( " MemberTableField::delete: Bad parameters: Group= $groupID , Member= $memberID " , E_USER_ERROR );
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
return FormResponse :: respond ();
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
/**
* #################################
* Utility Functions
* #################################
*/
function getParentClass () {
2008-02-25 03:10:37 +01:00
return 'Group' ;
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:39:59 +02:00
2009-02-04 21:36:23 +01:00
function getParentIdName ( $childClass , $parentClass ) {
2008-02-25 03:10:37 +01:00
return 'GroupID' ;
2007-07-19 12:40:05 +02:00
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
/**
* #################################
* Custom Functions
* #################################
*/
2009-02-04 21:36:23 +01:00
/**
* Customise an existing DataObjectSet of Member
* objects with a GroupID .
*
* @ param DataObjectSet $members Set of Member objects to customise
* @ param Group $group Group object to customise with
* @ return DataObjectSet Customised set of Member objects
*/
2007-07-19 12:40:05 +02:00
function memberListWithGroupID ( $members , $group ) {
$newMembers = new DataObjectSet ();
foreach ( $members as $member ) {
2008-02-25 03:10:37 +01:00
$newMembers -> push ( $member -> customise ( array ( 'GroupID' => $group -> ID )));
2007-07-19 12:40:05 +02:00
}
return $newMembers ;
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
function setGroup ( $group ) {
$this -> group = $group ;
}
2009-02-03 04:22:20 +01:00
2007-07-19 12:40:05 +02:00
function setController ( $controller ) {
$this -> controller = $controller ;
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
function GetControllerName () {
return $this -> controller -> class ;
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
/**
* Add existing member to group by name ( with JS - autocompletion )
*/
function AddRecordForm () {
$fields = new FieldSet ();
2009-02-03 04:22:20 +01:00
foreach ( $this -> FieldList () as $fieldName => $fieldTitle ) {
2009-03-10 22:59:19 +01:00
// 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 ));
}
2007-07-19 12:40:05 +02:00
}
2008-02-25 03:10:37 +01:00
$fields -> push ( new HiddenField ( 'ctf[ID]' , null , $this -> group -> ID ));
2007-09-14 21:39:59 +02:00
2009-02-03 04:22:20 +01:00
$actions = new FieldSet (
new FormAction ( 'addtogroup' , _t ( 'MemberTableField.ADD' , 'Add' ))
);
return new TabularStyle (
new NestedForm (
new Form (
$this ,
'AddRecordForm' ,
$fields ,
$actions
)
2007-07-19 12:40:05 +02:00
)
2009-02-03 04:22:20 +01:00
);
2007-07-19 12:40:05 +02:00
}
2008-10-08 05:46:19 +02:00
/**
* 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 ();
$form -> saveInto ( $childData );
$childData -> write ();
$childData -> Groups () -> add ( $data [ 'GroupID' ]);
$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 () . '">' . $childData -> Title . '</a>' ,
$closeLink
);
$form -> sessionMessage ( $message , 'good' );
Director :: redirectBack ();
}
2007-07-19 12:40:05 +02:00
/**
* Cached version for getting the appropraite members for this particular group .
2007-09-14 21:39:59 +02:00
*
2007-07-19 12:40:05 +02:00
* This includes getting inherited groups , such as groups under groups .
*/
2009-02-03 04:22:20 +01:00
function sourceItems () {
2007-07-19 12:40:05 +02:00
// Caching.
if ( $this -> sourceItems ) {
return $this -> sourceItems ;
}
2007-09-14 21:39:59 +02:00
// Setup limits
2008-02-25 03:10:37 +01:00
$limitClause = '' ;
2007-07-19 12:40:05 +02:00
if ( isset ( $_REQUEST [ 'ctf' ][ $this -> Name ()][ 'start' ]) && is_numeric ( $_REQUEST [ 'ctf' ][ $this -> Name ()][ 'start' ])) {
$limitClause = ( $_REQUEST [ 'ctf' ][ $this -> Name ()][ 'start' ]) . " , { $this -> pageSize } " ;
} else {
$limitClause = " 0, { $this -> pageSize } " ;
}
// We use the group to get the members, as they already have the bulk of the look up functions
$start = isset ( $_REQUEST [ 'ctf' ][ $this -> Name ()][ 'start' ]) ? $_REQUEST [ 'ctf' ][ $this -> Name ()][ 'start' ] : 0 ;
2008-08-27 06:58:34 +02:00
2009-02-04 21:36:23 +01:00
$this -> sourceItems = $this -> group -> Members (
2009-02-03 04:22:20 +01:00
$this -> pageSize , // limit
$start , // offset
$this -> sourceFilter ,
$this -> sourceSort
);
2009-02-03 04:46:15 +01:00
// Because we are not used $this->upagedSourceItems any more, and the DataObjectSet is usually the source
// that a large member set runs out of memory. we disable it here.
//$this->unpagedSourceItems = $this->group->Members('', '', $this->sourceFilter, $this->sourceSort);
2007-07-19 12:40:05 +02:00
$this -> totalCount = ( $this -> sourceItems ) ? $this -> sourceItems -> TotalItems () : 0 ;
2009-02-03 04:22:20 +01:00
2007-07-19 12:40:05 +02:00
return $this -> sourceItems ;
}
2007-09-15 22:10:43 +02:00
2007-07-19 12:40:05 +02:00
function TotalCount () {
$this -> sourceItems (); // Called for its side-effect of setting total count
return $this -> totalCount ;
}
2008-09-12 05:22:56 +02:00
/**
* Handles item requests
* MemberTableField needs its own item request class so that it can overload the delete method
*/
function handleItem ( $request ) {
return new MemberTableField_ItemRequest ( $this , $request -> param ( 'ID' ));
}
2007-07-19 12:40:05 +02:00
}
2008-02-25 03:10:37 +01:00
/**
* Popup window for { @ link MemberTableField } .
* @ package cms
* @ subpackage security
*/
2007-07-19 12:40:05 +02:00
class MemberTableField_Popup extends ComplexTableField_Popup {
2008-02-25 03:10:37 +01:00
2007-07-19 12:40:05 +02:00
function __construct ( $controller , $name , $fields , $sourceClass , $readonly = false , $validator = null ) {
parent :: __construct ( $controller , $name , $fields , $sourceClass , $readonly , $validator );
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@63175 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-28 15:12:20 +02:00
Requirements :: javascript ( CMS_DIR . '/javascript/MemberTableField.js' );
Requirements :: javascript ( CMS_DIR . '/javascript/MemberTableField_popup.js' );
2007-07-19 12:40:05 +02:00
}
}
2008-09-12 05:22:56 +02:00
class MemberTableField_ItemRequest extends ComplexTableField_ItemRequest {
/**
* Deleting an item from a member table field should just remove that member from the group
*/
function delete () {
if ( $this -> ctf -> Can ( 'delete' ) !== true ) {
return false ;
}
$groupID = $this -> ctf -> sourceID ();
$this -> dataObj () -> Groups () -> remove ( $groupID );
}
}
2009-03-04 04:35:29 +01:00
?>