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 .
*
* Returns either :
* - provided members
* - members of a provided group
* - all members
* - members based on a search - query
*/
class MemberTableField extends ComplexTableField {
protected $members ;
protected $hidePassword ;
protected $pageSize ;
protected $detailFormValidator ;
protected $group ;
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
protected $template = " MemberTableField " ;
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
static $data_class = " Member " ;
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
protected $permissions = array (
" add " ,
" edit " ,
" delete "
);
private static $addedPermissions = array ();
private static $addedFields = array ();
private static $addedCsvFields = array ();
2007-09-15 22:10:43 +02:00
2007-07-19 12:40:05 +02:00
public static function addPermissions ( $addingPermissionList ) {
self :: $addedPermissions = $addingPermissionList ;
}
2007-09-15 22:10:43 +02:00
2007-07-19 12:40:05 +02:00
public static function addMembershipFields ( $addingFieldList , $addingCsvFieldList = null ) {
self :: $addedFields = $addingFieldList ;
$addingCsvFieldList == null ? self :: $addedCsvFields = $addingFieldList : self :: $addedCsvFields = $addingCsvFieldList ;
}
2007-09-15 22:10:43 +02:00
2007-07-19 12:40:05 +02:00
function __construct ( $controller , $name , $group , $members = null , $hidePassword = true , $pageLimit = 10 ) {
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
if ( $group ) {
if ( is_object ( $group )) {
$this -> group = $group ;
} else if ( is_numeric ( $group )){
$this -> group = DataObject :: get_by_id ( 'Group' , $group );
2007-09-14 21:39:59 +02:00
}
2007-07-19 12:40:05 +02:00
} else if ( is_numeric ( $_REQUEST [ 'ctf' ][ $this -> Name ()][ " ID " ])) {
$this -> group = DataObject :: get_by_id ( 'Group' , $_REQUEST [ 'ctf' ][ $this -> Name ()][ " ID " ]);
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
$sourceClass = $this -> stat ( " data_class " );
foreach ( self :: $addedPermissions as $permission )
array_push ( $this -> permissions , $permission );
$fieldList = array (
2007-09-14 21:39:59 +02:00
" FirstName " => " Firstname " ,
" Surname " => " Surname " ,
" Email " => " Email "
2007-07-19 12:40:05 +02:00
);
2007-09-15 22:10:43 +02:00
2007-07-19 12:40:05 +02:00
$csvFieldList = $fieldList ;
foreach ( self :: $addedCsvFields as $key => $value ) {
$csvFieldList [ $key ] = $value ;
}
2007-09-15 22:10:43 +02:00
2007-07-19 12:40:05 +02:00
foreach ( self :: $addedFields as $key => $value ) {
$fieldList [ $key ] = $value ;
}
2007-09-15 22:10:43 +02:00
2007-07-19 12:40:05 +02:00
if ( ! $hidePassword ) {
2007-09-14 21:39:59 +02:00
$fieldList [ " Password " ] = " Password " ;
2007-07-19 12:40:05 +02:00
}
2007-11-23 02:10:19 +01:00
// $detailFormFields = singleton(Object::getCustomClass($this->stat("data_class")))->getCMSFields();
2007-07-19 12:40:05 +02:00
if ( isset ( $_REQUEST [ 'ctf' ][ 'childID' ]) && $memberID = $_REQUEST [ 'ctf' ][ 'childID' ]) {
$SNG_member = DataObject :: get_by_id ( $this -> stat ( " data_class " ), $_REQUEST [ 'ctf' ][ 'childID' ]);
} else {
$SNG_member = singleton ( Object :: getCustomClass ( $this -> stat ( " data_class " )));
}
$detailFormFields = $SNG_member -> getCMSFields ();
$this -> detailFormValidator = $SNG_member -> getValidator ();
2007-09-15 22:10:43 +02:00
2007-07-19 12:40:05 +02:00
$this -> pageSize = $pageLimit ;
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
// Legacy: Use setCustomSourceItems() instead.
if ( $members ) {
$this -> customSourceItems = $this -> memberListWithGroupID ( $members , $group );
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
$this -> hidePassword = $hidePassword ;
2007-11-23 02:10:19 +01:00
parent :: __construct ( $controller , $name , $sourceClass , $fieldList );
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
Requirements :: javascript ( " cms/javascript/MemberTableField.js " );
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
// construct the filter and sort
if ( isset ( $_REQUEST [ 'MemberOrderByField' ])) {
$this -> sourceSort = " ` " . Convert :: raw2sql ( $_REQUEST [ 'MemberOrderByField' ]) . " ` " . Convert :: raw2sql ( $_REQUEST [ 'MemberOrderByOrder' ] );
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
// search
$search = isset ( $_REQUEST [ 'MemberSearch' ]) ? Convert :: raw2sql ( $_REQUEST [ 'MemberSearch' ]) : null ;
if ( ! empty ( $_REQUEST [ 'MemberSearch' ])) {
//$this->sourceFilter[] = "( `Email` LIKE '%$search%' OR `FirstName` LIKE '%$search%' OR `Surname` LIKE '%$search%' )";
$sourceF = " ( " ;
foreach ( $fieldList as $k => $v )
$sourceF .= " ` $k ` LIKE '% $search %' OR " ;
$this -> sourceFilter [] = substr ( $sourceF , 0 , - 3 ) . " ) " ;
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
// filter by groups
// TODO Not implemented yet
if ( isset ( $_REQUEST [ 'ctf' ][ $this -> Name ()][ 'GroupID' ]) && is_numeric ( $_REQUEST [ 'ctf' ][ $this -> Name ()][ 'GroupID' ])) {
$this -> sourceFilter [] = " `GroupID`=' { $_REQUEST [ 'ctf' ][ $this -> Name ()][ 'GroupID' ] } ' " ;
} elseif ( $this -> group ) {
//$this->sourceFilter[] = "`GroupID`='{$this->group->ID}'";
// If the table is not clean (without duplication), the total and navigation wil not work well, so uncheck the big line below
$this -> sourceFilter [] = " `Group_Members`.`ID` IN (SELECT `ID` FROM `Group_Members` WHERE `GroupID`=' { $this -> group -> ID } ' GROUP BY `MemberID` HAVING MIN(`ID`)) " ;
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
$this -> sourceJoin = " INNER JOIN `Group_Members` ON `MemberID`=`Member`.`ID` " ;
$this -> setFieldListCsv ( $csvFieldList );
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
/**
* Overridden functions
*/
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 () {
return " { $this -> PopupBaseLink () } &methodName=add " ;
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
function DetailForm () {
2007-11-23 02:10:19 +01:00
// Get all the requests
2007-09-15 22:11:06 +02:00
$ID = Convert :: raw2xml ( isset ( $_REQUEST [ 'ctf' ][ 'ID' ])
? $_REQUEST [ 'ctf' ][ 'ID' ]
: '' );
2007-07-19 12:40:05 +02:00
$childID = isset ( $_REQUEST [ 'ctf' ][ 'childID' ]) ? Convert :: raw2xml ( $_REQUEST [ 'ctf' ][ 'childID' ]) : 0 ;
$childClass = Convert :: raw2xml ( $_REQUEST [ 'fieldName' ]);
2007-11-23 02:10:19 +01:00
$this -> methodName = $_REQUEST [ 'methodName' ];
// used to discover fields if requested and for population of field
if ( is_numeric ( $childID )) {
// we have to use the basedataclass, otherwise we might exclude other subclasses
$childData = DataObject :: get_by_id ( ClassInfo :: baseDataClass ( $this -> sourceClass ), $childID );
}
$parentIdName = $this -> getParentIdName ( $this -> sourceClass , $this -> getParentClass ());
if ( ! $parentIdName ) {
user_error ( " ComplexTableField::DetailForm() DataObject does not seem to have an 'has-one'-relationship " , E_USER_WARNING );
return ;
}
// If the fieldset is passed, use it, else use the formfields returned
// from the object via a string method call.
if ( is_a ( $this -> detailFormFields , " Fieldset " )){
$detailFields = $this -> detailFormFields ;
} else if ( is_string ( $this -> detailFormFields )){
$functioncall = $this -> detailFormFields ;
if ( $childData -> hasMethod ( $functioncall )){
$detailFields = $childData -> $functioncall ();
}
} elseif ( ! $childData || $this -> methodName == 'add' ) {
$SNG_sourceClass = singleton ( $this -> sourceClass );
if ( is_numeric ( $ID ) && $this -> getParentClass ()) {
// make sure the relation-link is existing, even if we just add the sourceClass
// and didn't save it
$parentIDName = $this -> getParentIdName ( $this -> sourceClass , $this -> getParentClass ());
$SNG_sourceClass -> $parentIDName = $ID ;
}
$detailFields = $SNG_sourceClass -> getCMSFields ();
} else {
$detailFields = $childData -> getCMSFields ();
}
if ( $this -> getParentClass ()) {
$parentIdName = $this -> getParentIdName ( $this -> sourceClass , $this -> getParentClass ());
2007-07-19 12:40:05 +02:00
if ( ! $parentIdName ) {
2007-11-23 02:10:19 +01:00
user_error ( " ComplexTableField::DetailForm() Cannot automatically
determine 'has-one' - relationship to parent ,
please use setParentClass () to set it manually " ,
E_USER_WARNING );
2007-07-19 12:40:05 +02:00
return ;
}
2007-11-23 02:10:19 +01:00
// add relational fields
$detailFields -> push ( new HiddenField ( " ctf[parentClass] " , " " , $this -> getParentClass ()));
$detailFields -> push ( new HiddenField ( " $parentIdName " , " " , $ID ));
}
2007-07-19 12:40:05 +02:00
// the ID field confuses the Controller-logic in finding the right view for ReferencedField
2007-11-23 02:10:19 +01:00
$detailFields -> removeByName ( 'ID' );
2007-11-26 22:19:02 +01:00
$detailFields -> push ( new HiddenField ( " ctf[ID] " , " " , $ID ));
2007-07-19 12:40:05 +02:00
2007-11-23 02:10:19 +01:00
// add a namespaced ID instead thats "converted" by saveComplexTableField()
$detailFields -> push ( new HiddenField ( " ctf[childID] " , " " , $childID ));
$detailFields -> push ( new HiddenField ( " ctf[ClassName] " , " " , $this -> sourceClass ));
$form = new MemberTableField_Popup ( $this , " DetailForm " , $detailFields , $this -> sourceClass , false , $this -> detailFormValidator );
2007-07-19 12:40:05 +02:00
if ( is_numeric ( $childID )) {
2007-11-23 02:10:19 +01:00
if ( $this -> methodName == " show " || $this -> methodName == " edit " ) {
2007-07-19 12:40:05 +02:00
$childData = DataObject :: get_by_id ( $this -> sourceClass , $childID );
$form -> loadDataFrom ( $childData );
}
}
2007-11-23 02:10:19 +01:00
if ( $this -> methodName == " show " ) {
2007-07-19 12:40:05 +02:00
$form -> makeReadonly ();
}
return $form ;
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
function SearchForm () {
$searchFields = new FieldGroup (
new TextField ( 'MemberSearch' , 'Search' ),
new HiddenField ( " ctf[ID] " , '' , $this -> group -> ID ),
new HiddenField ( 'MemberFieldName' , '' , $this -> name ),
new HiddenField ( 'MemberDontShowPassword' , '' , $this -> hidePassword )
);
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
$orderByFields = new FieldGroup (
new LabelField ( 'Order by' ),
2007-09-14 21:39:59 +02:00
new FieldSet (
2007-07-19 12:40:05 +02:00
new DropdownField ( 'MemberOrderByField' , '' , array (
'FirstName' => 'FirstName' ,
'Surname' => 'Surname' ,
'Email' => 'Email'
)),
new DropdownField ( 'MemberOrderByOrder' , '' , array (
'ASC' => 'Ascending' ,
'DESC' => 'Descending'
))
)
);
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
$groups = DataObject :: get ( 'Group' );
$groupArray = array ( '' => 'Any group' );
foreach ( $groups as $group ) {
$groupArray [ $group -> ID ] = $group -> Title ;
}
$groupFields = new DropdownField ( 'MemberGroup' , 'Filter by group' , $groupArray );
2007-09-14 21:39:59 +02:00
2007-11-06 03:53:40 +01:00
$actionFields = new LiteralField ( 'MemberFilterButton' , '<input type="submit" class="action" name="MemberFilterButton" value="Filter" id="MemberFilterButton"/>' );
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
$fieldContainer = new FieldGroup (
$searchFields ,
// $orderByFields,
// $groupFields,
$actionFields
);
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' ]);
if ( ! is_numeric ( $data [ 'ctf' ][ 'ID' ])) {
FormResponse :: status_messsage ( 'Adding failed' , 'bad' );
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
$className = $this -> stat ( 'data_class' );
$record = new $className ();
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
$record -> update ( $data );
$record -> write ();
// To Avoid duplication in the Group_Members table if the ComponentSet.php is not modified just uncomment le line below
//if( ! $record->isInGroup( $data['ctf']['ID'] ) )
$record -> Groups () -> add ( $data [ 'ctf' ][ 'ID' ] );
2007-09-15 22:10:43 +02:00
2007-07-19 12:40:05 +02:00
$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 );
2007-09-16 18:33:05 +02:00
FormResponse :: status_message ( _t ( 'MemberTableField.ADDEDTOGROUP' , 'Added member to group' ), 'good' );
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 () {
$groupID = Convert :: raw2sql ( $_REQUEST [ " ctf " ][ " ID " ]);
$memberID = Convert :: raw2sql ( $_REQUEST [ " ctf " ][ " childID " ]);
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 () {
return " Group " ;
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
function getParentIdName ( $childClass , $parentClass ){
return " GroupID " ;
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
/**
* #################################
* Custom Functions
* #################################
*/
function memberListWithGroupID ( $members , $group ) {
$newMembers = new DataObjectSet ();
foreach ( $members as $member ) {
$newMembers -> push ( $member -> customise ( array ( " GroupID " => $group -> ID )));
}
return $newMembers ;
}
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
function setGroup ( $group ) {
$this -> group = $group ;
}
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 ();
foreach ( $this -> FieldList () as $fieldName => $fieldTitle ) {
$fields -> push ( new TextField ( $fieldName ));
}
$fields -> push ( new HiddenField ( " ctf[ID] " , null , $this -> group -> ID ));
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
return new TabularStyle ( new Form ( $this -> controller , 'AddRecordForm' ,
$fields ,
new FieldSet (
2007-09-16 18:33:05 +02:00
new FormAction ( " addtogroup " , _t ( 'MemberTableField.ADD' , 'Add' ))
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 .
*/
function sourceItems (){
// Caching.
if ( $this -> sourceItems ) {
return $this -> sourceItems ;
}
2007-09-14 21:39:59 +02:00
// Setup limits
2007-07-19 12:40:05 +02:00
$limitClause = " " ;
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 ;
$this -> sourceItems = $this -> group -> Members (
$this -> pageSize , // limit
$start , // offset
$this -> sourceFilter ,
$this -> sourceSort
);
$this -> unpagedSourceItems = $this -> group -> Members ( " " , " " , $this -> sourceFilter , $this -> sourceSort );
$this -> totalCount = ( $this -> sourceItems ) ? $this -> sourceItems -> TotalItems () : 0 ;
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 ;
}
}
class MemberTableField_Popup extends ComplexTableField_Popup {
function __construct ( $controller , $name , $fields , $sourceClass , $readonly = false , $validator = null ) {
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
// DO NOT CHANGE THE ORDER OF THESE JS FILES. THESE ARE ONLY REQUIRED FOR THIS INSTANCE !!!11onetwo
parent :: __construct ( $controller , $name , $fields , $sourceClass , $readonly , $validator );
Requirements :: javascript ( " cms/javascript/MemberTableField.js " );
Requirements :: javascript ( " cms/javascript/MemberTableField_popup.js " );
}
function saveComplexTableField () {
$id = Convert :: raw2sql ( $_REQUEST [ 'ctf' ][ 'childID' ]);
if ( is_numeric ( $id )) {
$childObject = DataObject :: get_by_id ( $this -> sourceClass , $id );
} else {
$childObject = new $this -> sourceClass ();
}
$this -> saveInto ( $childObject );
$childObject -> write ();
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
$childObject -> Groups () -> add ( $_REQUEST [ 'ctf' ][ 'ID' ]);
2007-09-14 21:39:59 +02:00
2007-07-19 12:40:05 +02:00
// if ajax-call in an iframe, close window by javascript, else redirect to referrer
if ( ! Director :: is_ajax ()) {
Director :: redirect ( substr ( $_SERVER [ 'REQUEST_URI' ], 0 , strpos ( $_SERVER [ 'REQUEST_URI' ], " ? " )));
}
}
}
?>