mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
ENHANCEMENT: Refactored MemberTableList field to make better use of DataList and ManyManyList. Refactored ComplexTableField and TableListField to, stripping out as much model logic as possible.
This commit is contained in:
parent
3a17d5c427
commit
4a061fd071
@ -33,8 +33,6 @@ class MemberTableField extends ComplexTableField {
|
|||||||
|
|
||||||
public $itemClass = 'MemberTableField_Item';
|
public $itemClass = 'MemberTableField_Item';
|
||||||
|
|
||||||
static $data_class = 'Member';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the page size for this table.
|
* Set the page size for this table.
|
||||||
* @var int
|
* @var int
|
||||||
@ -60,8 +58,24 @@ class MemberTableField extends ComplexTableField {
|
|||||||
* @param boolean $hidePassword Hide the password field or not in the summary?
|
* @param boolean $hidePassword Hide the password field or not in the summary?
|
||||||
*/
|
*/
|
||||||
function __construct($controller, $name, $group = null, $members = null, $hidePassword = true) {
|
function __construct($controller, $name, $group = null, $members = null, $hidePassword = true) {
|
||||||
$sourceClass = self::$data_class;
|
|
||||||
$SNG_member = singleton($sourceClass);
|
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->Name()]["ID"]) && is_numeric($_REQUEST['ctf'][$this->Name()]["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->Name()]["ID"]);
|
||||||
|
$this->group = $group;
|
||||||
|
$members = $group->Members();
|
||||||
|
} else {
|
||||||
|
$members = DataObject::get("Member");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$SNG_member = singleton('Member');
|
||||||
$fieldList = $SNG_member->summaryFields();
|
$fieldList = $SNG_member->summaryFields();
|
||||||
$memberDbFields = $SNG_member->db();
|
$memberDbFields = $SNG_member->db();
|
||||||
$csvFieldList = array();
|
$csvFieldList = array();
|
||||||
@ -70,52 +84,24 @@ class MemberTableField extends ComplexTableField {
|
|||||||
$csvFieldList[$field] = $field;
|
$csvFieldList[$field] = $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($group) {
|
|
||||||
if(is_object($group)) {
|
|
||||||
$this->group = $group;
|
|
||||||
} elseif(is_numeric($group)) {
|
|
||||||
$this->group = DataObject::get_by_id('Group', $group);
|
|
||||||
}
|
|
||||||
} else if(isset($_REQUEST['ctf'][$this->Name()]["ID"]) && is_numeric($_REQUEST['ctf'][$this->Name()]["ID"])) {
|
|
||||||
$this->group = DataObject::get_by_id('Group', $_REQUEST['ctf'][$this->Name()]["ID"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$hidePassword) {
|
if(!$hidePassword) {
|
||||||
$fieldList["SetPassword"] = "Password";
|
$fieldList["SetPassword"] = "Password";
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->hidePassword = $hidePassword;
|
$this->hidePassword = $hidePassword;
|
||||||
|
|
||||||
// @todo shouldn't this use $this->group? It's unclear exactly
|
// Add a search filter
|
||||||
// what group it should be customising the custom Member set with.
|
|
||||||
if($members && $group) {
|
|
||||||
$this->setCustomSourceItems($this->memberListWithGroupID($members, $group));
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct($controller, $name, $sourceClass, $fieldList);
|
|
||||||
|
|
||||||
$SQL_search = isset($_REQUEST['MemberSearch']) ? Convert::raw2sql($_REQUEST['MemberSearch']) : null;
|
$SQL_search = isset($_REQUEST['MemberSearch']) ? Convert::raw2sql($_REQUEST['MemberSearch']) : null;
|
||||||
if(!empty($_REQUEST['MemberSearch'])) {
|
if(!empty($_REQUEST['MemberSearch'])) {
|
||||||
$searchFilters = array();
|
$searchFilters = array();
|
||||||
foreach($SNG_member->searchableFields() as $fieldName => $fieldSpec) {
|
foreach($SNG_member->searchableFields() as $fieldName => $fieldSpec) {
|
||||||
if(strpos($fieldName, '.') === false) $searchFilters[] = "\"$fieldName\" LIKE '%{$SQL_search}%'";
|
if(strpos($fieldName, '.') === false) $searchFilters[] = "\"$fieldName\" LIKE '%{$SQL_search}%'";
|
||||||
}
|
}
|
||||||
$this->sourceFilter[] = '(' . implode(' OR ', $searchFilters) . ')';
|
$members = $members->filter('(' . implode(' OR ', $searchFilters) . ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->group) {
|
parent::__construct($controller, $name, $members, $fieldList);
|
||||||
user_error("MemberTableField's group setting doesn't yet work in the new-orm branch", E_USER_WARNING);
|
|
||||||
/*
|
|
||||||
$groupIDs = array($this->group->ID);
|
|
||||||
if($this->group->AllChildren()) $groupIDs = array_merge($groupIDs, $this->group->AllChildren()->column('ID'));
|
|
||||||
$this->sourceFilter[] = sprintf(
|
|
||||||
'"Group_Members"."GroupID" IN (%s)',
|
|
||||||
implode(',', $groupIDs)
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->sourceJoin = " INNER JOIN \"Group_Members\" ON \"MemberID\"=\"Member\".\"ID\"";
|
|
||||||
$this->setFieldListCsv($csvFieldList);
|
$this->setFieldListCsv($csvFieldList);
|
||||||
$this->setPageSize($this->stat('page_size'));
|
$this->setPageSize($this->stat('page_size'));
|
||||||
}
|
}
|
||||||
@ -130,14 +116,6 @@ class MemberTableField extends ComplexTableField {
|
|||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sourceID() {
|
|
||||||
return ($this->group) ? $this->group->ID : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function AddLink() {
|
|
||||||
return Controller::join_links($this->Link(), 'add');
|
|
||||||
}
|
|
||||||
|
|
||||||
function SearchForm() {
|
function SearchForm() {
|
||||||
$groupID = (isset($this->group)) ? $this->group->ID : 0;
|
$groupID = (isset($this->group)) ? $this->group->ID : 0;
|
||||||
$query = isset($_GET['MemberSearch']) ? $_GET['MemberSearch'] : null;
|
$query = isset($_GET['MemberSearch']) ? $_GET['MemberSearch'] : null;
|
||||||
@ -168,6 +146,7 @@ class MemberTableField extends ComplexTableField {
|
|||||||
if(!$token->checkRequest($this->controller->getRequest())) return $this->httpError(400);
|
if(!$token->checkRequest($this->controller->getRequest())) return $this->httpError(400);
|
||||||
|
|
||||||
$data = $_REQUEST;
|
$data = $_REQUEST;
|
||||||
|
|
||||||
$groupID = (isset($data['ctf']['ID'])) ? $data['ctf']['ID'] : null;
|
$groupID = (isset($data['ctf']['ID'])) ? $data['ctf']['ID'] : null;
|
||||||
|
|
||||||
if(!is_numeric($groupID)) {
|
if(!is_numeric($groupID)) {
|
||||||
@ -177,7 +156,7 @@ class MemberTableField extends ComplexTableField {
|
|||||||
|
|
||||||
// Get existing record either by ID or unique identifier.
|
// Get existing record either by ID or unique identifier.
|
||||||
$identifierField = Member::get_unique_identifier_field();
|
$identifierField = Member::get_unique_identifier_field();
|
||||||
$className = self::$data_class;
|
$className = 'Member';
|
||||||
$record = null;
|
$record = null;
|
||||||
if(isset($data[$identifierField])) {
|
if(isset($data[$identifierField])) {
|
||||||
$record = DataObject::get_one(
|
$record = DataObject::get_one(
|
||||||
@ -204,7 +183,7 @@ class MemberTableField extends ComplexTableField {
|
|||||||
$valid = $record->validate();
|
$valid = $record->validate();
|
||||||
if($valid->valid()) {
|
if($valid->valid()) {
|
||||||
$record->write();
|
$record->write();
|
||||||
$record->Groups()->add($groupID);
|
$this->getDataList()->add($record);
|
||||||
|
|
||||||
$this->sourceItems();
|
$this->sourceItems();
|
||||||
|
|
||||||
@ -232,68 +211,12 @@ class MemberTableField extends ComplexTableField {
|
|||||||
return FormResponse::respond();
|
return FormResponse::respond();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Custom delete implementation:
|
|
||||||
* Remove member from group rather than from the database
|
|
||||||
*/
|
|
||||||
function delete() {
|
|
||||||
// Protect against CSRF on destructive action
|
|
||||||
$token = $this->getForm()->getSecurityToken();
|
|
||||||
// TODO Not sure how this is called, using $_REQUEST to be on the safe side
|
|
||||||
if(!$token->check($_REQUEST['SecurityID'])) return $this->httpError(400);
|
|
||||||
|
|
||||||
$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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FormResponse::respond();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* #################################
|
|
||||||
* Utility Functions
|
|
||||||
* #################################
|
|
||||||
*/
|
|
||||||
function getParentClass() {
|
|
||||||
return 'Group';
|
|
||||||
}
|
|
||||||
|
|
||||||
function getParentIdName($childClass, $parentClass) {
|
|
||||||
return 'GroupID';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* #################################
|
* #################################
|
||||||
* Custom Functions
|
* Custom Functions
|
||||||
* #################################
|
* #################################
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
function memberListWithGroupID($members, $group) {
|
|
||||||
$newMembers = new DataObjectSet();
|
|
||||||
foreach($members as $member) {
|
|
||||||
$newMembers->push($member->customise(array('GroupID' => $group->ID)));
|
|
||||||
}
|
|
||||||
return $newMembers;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setGroup($group) {
|
|
||||||
$this->group = $group;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Group
|
* @return Group
|
||||||
*/
|
*/
|
||||||
@ -301,14 +224,6 @@ class MemberTableField extends ComplexTableField {
|
|||||||
return $this->group;
|
return $this->group;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setController($controller) {
|
|
||||||
$this->controller = $controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
function GetControllerName() {
|
|
||||||
return $this->controller->class;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add existing member to group by name (with JS-autocompletion)
|
* Add existing member to group by name (with JS-autocompletion)
|
||||||
*/
|
*/
|
||||||
@ -390,66 +305,6 @@ class MemberTableField extends ComplexTableField {
|
|||||||
|
|
||||||
$this->controller->redirectBack();
|
$this->controller->redirectBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Cached version for getting the appropraite members for this particular group.
|
|
||||||
*
|
|
||||||
* This includes getting inherited groups, such as groups under groups.
|
|
||||||
*/
|
|
||||||
function sourceItems() {
|
|
||||||
// Caching.
|
|
||||||
if($this->sourceItems) {
|
|
||||||
return $this->sourceItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup limits
|
|
||||||
$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 = false;
|
|
||||||
|
|
||||||
if($this->group) {
|
|
||||||
$this->sourceItems = $this->group->Members(
|
|
||||||
$this->pageSize, // limit
|
|
||||||
$start, // offset
|
|
||||||
$this->sourceFilter,
|
|
||||||
$this->sourceSort
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$this->sourceItems = DataObject::get(self::$data_class,
|
|
||||||
$this->sourceFilter,
|
|
||||||
$this->sourceSort,
|
|
||||||
null,
|
|
||||||
array('limit' => $this->pageSize, 'start' => $start)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// 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);
|
|
||||||
$this->totalCount = ($this->sourceItems) ? $this->sourceItems->TotalItems() : 0;
|
|
||||||
|
|
||||||
return $this->sourceItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
function TotalCount() {
|
|
||||||
$this->sourceItems(); // Called for its side-effect of setting total count
|
|
||||||
return $this->totalCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -460,7 +315,7 @@ class MemberTableField extends ComplexTableField {
|
|||||||
class MemberTableField_Popup extends ComplexTableField_Popup {
|
class MemberTableField_Popup extends ComplexTableField_Popup {
|
||||||
|
|
||||||
function __construct($controller, $name, $fields, $validator, $readonly, $dataObject) {
|
function __construct($controller, $name, $fields, $validator, $readonly, $dataObject) {
|
||||||
$group = ($controller instanceof MemberTableField) ? $controller->getGroup() : $controller->getParent()->getGroup();
|
$group = ($controller instanceof MemberTableField) ? $controller->getGroup() : $controller->getParentController()->getGroup();
|
||||||
// Set default groups - also implemented in AddForm()
|
// Set default groups - also implemented in AddForm()
|
||||||
if($group) {
|
if($group) {
|
||||||
$groupsField = $fields->dataFieldByName('Groups');
|
$groupsField = $fields->dataFieldByName('Groups');
|
||||||
@ -513,44 +368,4 @@ class MemberTableField_Item extends ComplexTableField_Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @package cms
|
|
||||||
* @subpackage security
|
|
||||||
*/
|
|
||||||
|
|
||||||
class MemberTableField_ItemRequest extends ComplexTableField_ItemRequest {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deleting an item from a member table field should just remove that member from the group
|
|
||||||
*/
|
|
||||||
function delete($request) {
|
|
||||||
// Protect against CSRF on destructive action
|
|
||||||
$token = $this->ctf->getForm()->getSecurityToken();
|
|
||||||
if(!$token->checkRequest($request)) return $this->httpError('400');
|
|
||||||
|
|
||||||
if($this->ctf->Can('delete') !== true) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if a group limitation is set on the table, remove relation.
|
|
||||||
// otherwise remove the record from the database
|
|
||||||
if($this->ctf->getGroup()) {
|
|
||||||
$groupID = $this->ctf->sourceID();
|
|
||||||
$group = DataObject::get_by_id('Group', $groupID);
|
|
||||||
|
|
||||||
// Remove from group and all child groups
|
|
||||||
foreach($group->getAllChildren() as $subGroup) {
|
|
||||||
$this->dataObj()->Groups()->remove($subGroup);
|
|
||||||
}
|
|
||||||
$this->dataObj()->Groups()->remove($groupID);
|
|
||||||
} else {
|
|
||||||
$this->dataObj()->delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getParent() {
|
|
||||||
return $this->ctf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -305,7 +305,6 @@ MemberFilterButton.prototype = {
|
|||||||
updateURL += '&' + this.inputFields[index].name + '=' + encodeURIComponent( this.inputFields[index].value );
|
updateURL += '&' + this.inputFields[index].name + '=' + encodeURIComponent( this.inputFields[index].value );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateURL += ($('SecurityID') ? '&SecurityID=' + $('SecurityID').value : '');
|
|
||||||
|
|
||||||
jQuery($(fieldID)).get(updateURL, null, function() {Behaviour.apply($(fieldID), true);});
|
jQuery($(fieldID)).get(updateURL, null, function() {Behaviour.apply($(fieldID), true);});
|
||||||
} catch(er) {
|
} catch(er) {
|
||||||
|
@ -255,7 +255,7 @@ JS;
|
|||||||
}
|
}
|
||||||
|
|
||||||
$pageStart = (isset($_REQUEST['ctf'][$this->Name()]['start']) && is_numeric($_REQUEST['ctf'][$this->Name()]['start'])) ? $_REQUEST['ctf'][$this->Name()]['start'] : 0;
|
$pageStart = (isset($_REQUEST['ctf'][$this->Name()]['start']) && is_numeric($_REQUEST['ctf'][$this->Name()]['start'])) ? $_REQUEST['ctf'][$this->Name()]['start'] : 0;
|
||||||
$sourceItems->setPageLimits($pageStart, $this->pageSize, $this->totalCount);
|
$sourceItems->setPageLimits($pageStart, $this->pageSize, $this->TotalCount());
|
||||||
|
|
||||||
$output = new DataObjectSet();
|
$output = new DataObjectSet();
|
||||||
foreach($sourceItems as $pageIndex=>$item) {
|
foreach($sourceItems as $pageIndex=>$item) {
|
||||||
@ -343,85 +343,6 @@ JS;
|
|||||||
$this->controller = $controller;
|
$this->controller = $controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines on which relation-class the DetailForm is saved
|
|
||||||
* by looking at the surrounding form-record.
|
|
||||||
*
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
function getParentClass() {
|
|
||||||
if($this->parentClass === false) {
|
|
||||||
// purposely set parent-relation to false
|
|
||||||
return false;
|
|
||||||
} elseif(!empty($this->parentClass)) {
|
|
||||||
return $this->parentClass;
|
|
||||||
} elseif($this->form && $this->form->getRecord()) {
|
|
||||||
return $this->form->getRecord()->ClassName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the record in which the CTF resides, if it exists.
|
|
||||||
*/
|
|
||||||
function getParentRecord() {
|
|
||||||
if($this->form && $record = $this->form->getRecord()) {
|
|
||||||
return $record;
|
|
||||||
} else {
|
|
||||||
$parentID = (int)$this->sourceID();
|
|
||||||
$parentClass = $this->getParentClass();
|
|
||||||
|
|
||||||
if($parentClass) {
|
|
||||||
if($parentID) return DataObject::get_by_id($parentClass, $parentID);
|
|
||||||
else return singleton($parentClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Optional) Setter for a correct parent-relation-class.
|
|
||||||
* Defaults to the record loaded into the surrounding form as a fallback.
|
|
||||||
* Caution: Please use the classname, not the actual column-name in the database.
|
|
||||||
*
|
|
||||||
* @param $className string
|
|
||||||
*/
|
|
||||||
function setParentClass($className) {
|
|
||||||
$this->parentClass = $className;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the db-fieldname of the currently used has_one-relationship.
|
|
||||||
*/
|
|
||||||
function getParentIdName($parentClass, $childClass) {
|
|
||||||
return $this->getParentIdNameRelation($childClass, $parentClass, 'has_one');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manually overwrites the parent-ID relations.
|
|
||||||
* @see setParentClass()
|
|
||||||
*
|
|
||||||
* @param String $str Example: FamilyID (when one Individual has_one Family)
|
|
||||||
*/
|
|
||||||
function setParentIdName($str) {
|
|
||||||
$this->parentIdName = $str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the db-fieldname of the currently used relationship.
|
|
||||||
* Note: constructed resolve ambiguous cases in the same manner as
|
|
||||||
* DataObject::getComponentJoinField()
|
|
||||||
*/
|
|
||||||
function getParentIdNameRelation($parentClass, $childClass, $relation) {
|
|
||||||
if($this->parentIdName) return $this->parentIdName;
|
|
||||||
|
|
||||||
$relations = array_flip(singleton($parentClass)->$relation());
|
|
||||||
|
|
||||||
$classes = array_reverse(ClassInfo::ancestry($childClass));
|
|
||||||
foreach($classes as $class) {
|
|
||||||
if(isset($relations[$class])) return $relations[$class] . 'ID';
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setTemplatePopup($template) {
|
function setTemplatePopup($template) {
|
||||||
$this->templatePopup = $template;
|
$this->templatePopup = $template;
|
||||||
}
|
}
|
||||||
@ -458,45 +379,8 @@ JS;
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getFieldsFor($childData) {
|
function getFieldsFor($childData) {
|
||||||
$hasManyRelationName = null;
|
|
||||||
$manyManyRelationName = null;
|
|
||||||
|
|
||||||
// See if our parent class has any many_many relations by this source class
|
|
||||||
if($parentClass = $this->getParentRecord()) {
|
|
||||||
$manyManyRelations = $parentClass->many_many();
|
|
||||||
$manyManyRelationName = null;
|
|
||||||
$manyManyComponentSet = null;
|
|
||||||
|
|
||||||
$hasManyRelations = $parentClass->has_many();
|
|
||||||
$hasManyRelationName = null;
|
|
||||||
$hasManyComponentSet = null;
|
|
||||||
|
|
||||||
if($manyManyRelations) foreach($manyManyRelations as $relation => $class) {
|
|
||||||
if($class == $this->sourceClass()) {
|
|
||||||
$manyManyRelationName = $relation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($hasManyRelations) foreach($hasManyRelations as $relation => $class) {
|
|
||||||
if($class == $this->sourceClass()) {
|
|
||||||
$hasManyRelationName = $relation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the relation value to related records
|
|
||||||
if(!$childData->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->getParentClass(), $this->sourceClass());
|
|
||||||
$childData->$parentIDName = $this->sourceID();
|
|
||||||
}
|
|
||||||
|
|
||||||
$detailFields = $this->getCustomFieldsFor($childData);
|
$detailFields = $this->getCustomFieldsFor($childData);
|
||||||
|
|
||||||
if($this->getParentClass() && $hasManyRelationName && $childData->ID) {
|
|
||||||
$hasManyComponentSet = $parentClass->getComponents($hasManyRelationName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// the ID field confuses the Controller-logic in finding the right view for ReferencedField
|
// the ID field confuses the Controller-logic in finding the right view for ReferencedField
|
||||||
$detailFields->removeByName('ID');
|
$detailFields->removeByName('ID');
|
||||||
|
|
||||||
@ -505,9 +389,7 @@ JS;
|
|||||||
$detailFields->push(new HiddenField('ctf[childID]', '', $childData->ID));
|
$detailFields->push(new HiddenField('ctf[childID]', '', $childData->ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a namespaced ID instead thats "converted" by saveComplexTableField()
|
/* TODO: Figure out how to implement this
|
||||||
$detailFields->push(new HiddenField('ctf[ClassName]', '', $this->sourceClass()));
|
|
||||||
|
|
||||||
if($this->getParentClass()) {
|
if($this->getParentClass()) {
|
||||||
$detailFields->push(new HiddenField('ctf[parentClass]', '', $this->getParentClass()));
|
$detailFields->push(new HiddenField('ctf[parentClass]', '', $this->getParentClass()));
|
||||||
|
|
||||||
@ -518,6 +400,7 @@ JS;
|
|||||||
$detailFields->push(new HiddenField($parentIdName, '', $this->sourceID()));
|
$detailFields->push(new HiddenField($parentIdName, '', $this->sourceID()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
return $detailFields;
|
return $detailFields;
|
||||||
}
|
}
|
||||||
@ -689,7 +572,7 @@ class ComplexTableField_ItemRequest extends TableListField_ItemRequest {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->dataObj()->delete();
|
$this->ctf->getDataList()->removeByID($this->itemID);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -761,7 +644,7 @@ class ComplexTableField_ItemRequest extends TableListField_ItemRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save this item into the given relationship
|
// Save this item into the given relationship
|
||||||
$this->ctf->getDataList()->add($childData);
|
$this->ctf->getDataList()->add($dataObject);
|
||||||
|
|
||||||
$referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null;
|
$referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null;
|
||||||
|
|
||||||
@ -798,16 +681,16 @@ class ComplexTableField_ItemRequest extends TableListField_ItemRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function PopupLastLink() {
|
function PopupLastLink() {
|
||||||
if(!isset($_REQUEST['ctf']['start']) || !is_numeric($_REQUEST['ctf']['start']) || $_REQUEST['ctf']['start'] == $this->totalCount-1) {
|
if(!isset($_REQUEST['ctf']['start']) || !is_numeric($_REQUEST['ctf']['start']) || $_REQUEST['ctf']['start'] == $this->TotalCount()-1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$start = $this->totalCount - 1;
|
$start = $this->TotalCount - 1;
|
||||||
return Controller::join_links($this->Link(), "$this->methodName?ctf[start]={$start}");
|
return Controller::join_links($this->Link(), "$this->methodName?ctf[start]={$start}");
|
||||||
}
|
}
|
||||||
|
|
||||||
function PopupNextLink() {
|
function PopupNextLink() {
|
||||||
if(!isset($_REQUEST['ctf']['start']) || !is_numeric($_REQUEST['ctf']['start']) || $_REQUEST['ctf']['start'] == $this->totalCount-1) {
|
if(!isset($_REQUEST['ctf']['start']) || !is_numeric($_REQUEST['ctf']['start']) || $_REQUEST['ctf']['start'] == $this->TotalCount()-1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -836,13 +719,13 @@ class ComplexTableField_ItemRequest extends TableListField_ItemRequest {
|
|||||||
$result = new DataObjectSet();
|
$result = new DataObjectSet();
|
||||||
if($currentItem < 6) {
|
if($currentItem < 6) {
|
||||||
$offset = 1;
|
$offset = 1;
|
||||||
} elseif($this->totalCount - $currentItem <= 4) {
|
} elseif($this->TotalCount() - $currentItem <= 4) {
|
||||||
$offset = $currentItem - (10 - ($this->totalCount - $currentItem));
|
$offset = $currentItem - (10 - ($this->TotalCount() - $currentItem));
|
||||||
$offset = $offset <= 0 ? 1 : $offset;
|
$offset = $offset <= 0 ? 1 : $offset;
|
||||||
} else {
|
} else {
|
||||||
$offset = $currentItem - 5;
|
$offset = $currentItem - 5;
|
||||||
}
|
}
|
||||||
for($i = $offset;$i <= $offset + $this->pageSize && $i <= $this->totalCount;$i++) {
|
for($i = $offset;$i <= $offset + $this->pageSize && $i <= $this->TotalCount();$i++) {
|
||||||
$start = $i - 1;
|
$start = $i - 1;
|
||||||
$links['link'] = Controller::join_links($this->Link() . "$this->methodName?ctf[start]={$start}");
|
$links['link'] = Controller::join_links($this->Link() . "$this->methodName?ctf[start]={$start}");
|
||||||
$links['number'] = $i;
|
$links['number'] = $i;
|
||||||
@ -863,13 +746,6 @@ class ComplexTableField_ItemRequest extends TableListField_ItemRequest {
|
|||||||
* #################################
|
* #################################
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the db-fieldname of the currently used has_one-relationship.
|
|
||||||
*/
|
|
||||||
function getParentIdName($parentClass, $childClass) {
|
|
||||||
return $this->getParentIdNameRelation($childClass, $parentClass, 'has_one');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manually overwrites the parent-ID relations.
|
* Manually overwrites the parent-ID relations.
|
||||||
* @see setParentClass()
|
* @see setParentClass()
|
||||||
@ -877,23 +753,7 @@ class ComplexTableField_ItemRequest extends TableListField_ItemRequest {
|
|||||||
* @param String $str Example: FamilyID (when one Individual has_one Family)
|
* @param String $str Example: FamilyID (when one Individual has_one Family)
|
||||||
*/
|
*/
|
||||||
function setParentIdName($str) {
|
function setParentIdName($str) {
|
||||||
$this->parentIdName = $str;
|
throw new Exception("setParentIdName is no longer necessary");
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the db-fieldname of the currently used relationship.
|
|
||||||
*/
|
|
||||||
function getParentIdNameRelation($parentClass, $childClass, $relation) {
|
|
||||||
if($this->parentIdName) return $this->parentIdName;
|
|
||||||
|
|
||||||
$relations = singleton($parentClass)->$relation();
|
|
||||||
$classes = ClassInfo::ancestry($childClass);
|
|
||||||
if($relations) {
|
|
||||||
foreach($relations as $k => $v) {
|
|
||||||
if(array_key_exists($v, $classes)) return $k . 'ID';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTemplatePopup($template) {
|
function setTemplatePopup($template) {
|
||||||
|
@ -134,14 +134,6 @@ class TableListField extends FormField {
|
|||||||
*/
|
*/
|
||||||
protected $customCsvQuery;
|
protected $customCsvQuery;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var $customSourceItems DataObjectSet Use the manual setting of a result-set only as a last-resort
|
|
||||||
* for sets which can't be resolved in a single query.
|
|
||||||
*
|
|
||||||
* @todo Add pagination support for customSourceItems.
|
|
||||||
*/
|
|
||||||
protected $customSourceItems;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Character to seperate exported columns in the CSV file
|
* Character to seperate exported columns in the CSV file
|
||||||
*/
|
*/
|
||||||
@ -166,12 +158,6 @@ class TableListField extends FormField {
|
|||||||
"\n"=>"",
|
"\n"=>"",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int Shows total count regardless or pagination
|
|
||||||
*/
|
|
||||||
protected $totalCount;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var boolean Trigger pagination
|
* @var boolean Trigger pagination
|
||||||
*/
|
*/
|
||||||
@ -240,22 +226,29 @@ class TableListField extends FormField {
|
|||||||
|
|
||||||
protected $__cachedQuery;
|
protected $__cachedQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a flag that enables some backward-compatibility helpers.
|
||||||
|
*/
|
||||||
|
private $getDataListFromForm;
|
||||||
|
|
||||||
function __construct($name, $sourceClass = null, $fieldList = null, $sourceFilter = null,
|
function __construct($name, $sourceClass = null, $fieldList = null, $sourceFilter = null,
|
||||||
$sourceSort = null, $sourceJoin = null) {
|
$sourceSort = null, $sourceJoin = null) {
|
||||||
|
|
||||||
$this->fieldList = ($fieldList) ? $fieldList : singleton($sourceClass)->summaryFields();
|
|
||||||
|
|
||||||
if($sourceClass) {
|
if($sourceClass) {
|
||||||
// You can optionally pass a DataList as the 2nd argument to the constructor
|
// You can optionally pass a DataList/DataObjectSet
|
||||||
if($sourceClass instanceof DataList) {
|
if($sourceClass instanceof DataObjectSet) {
|
||||||
$this->dataList = $sourceClass;
|
$this->dataList = $sourceClass;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$this->dataList = DataObject::get($sourceClass)->filter($sourceFilter)
|
$this->dataList = DataObject::get($sourceClass)->filter($sourceFilter)
|
||||||
->sort($sourceSort)->join($sourceJoin);
|
->sort($sourceSort)->join($sourceJoin);
|
||||||
|
// Grab it from the form relation, if available.
|
||||||
|
$this->getDataListFromForm = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->fieldList = ($fieldList) ? $fieldList : singleton($this->sourceClass())->summaryFields();
|
||||||
|
|
||||||
$this->readOnly = false;
|
$this->readOnly = false;
|
||||||
|
|
||||||
parent::__construct($name);
|
parent::__construct($name);
|
||||||
@ -271,7 +264,10 @@ class TableListField extends FormField {
|
|||||||
);
|
);
|
||||||
|
|
||||||
function sourceClass() {
|
function sourceClass() {
|
||||||
return $this->getDataList()->dataClass();
|
$list = $this->getDataList();
|
||||||
|
if(method_exists($list, 'dataClass')) return $list->dataClass();
|
||||||
|
// Failover for DataObjectSet
|
||||||
|
else return get_class($list->First());
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleItem($request) {
|
function handleItem($request) {
|
||||||
@ -358,13 +354,10 @@ JS
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
function isFieldSortable($fieldName) {
|
function isFieldSortable($fieldName) {
|
||||||
if($this->customSourceItems || $this->disableSorting) {
|
if($this->disableSorting) return false;
|
||||||
return false;
|
$list = $this->getDataList();
|
||||||
}
|
if(method_exists($list,'canSortBy')) return $list->canSortBy($fieldName);
|
||||||
|
else return false;
|
||||||
if(!$this->__cachedQuery) $this->__cachedQuery = $this->getQuery();
|
|
||||||
|
|
||||||
return $this->__cachedQuery->canSortBy($fieldName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -400,45 +393,42 @@ JS
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setCustomSourceItems(DataObjectSet $items) {
|
function setCustomSourceItems(DataObjectSet $items) {
|
||||||
|
user_error('TableList::setCustomSourceItems() deprecated, just pass the items into the constructor', E_USER_WARNING);
|
||||||
|
|
||||||
// The type-hinting above doesn't seem to work consistently
|
// The type-hinting above doesn't seem to work consistently
|
||||||
if($items instanceof DataObjectSet) {
|
if($items instanceof DataObjectSet) {
|
||||||
$this->customSourceItems = $items;
|
$this->dataList = $items;
|
||||||
} else {
|
} else {
|
||||||
user_error('TableList::setCustomSourceItems() should be passed a DataObjectSet', E_USER_WARNING);
|
user_error('TableList::setCustomSourceItems() should be passed a DataObjectSet', E_USER_WARNING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get items, with sort & limit applied
|
||||||
|
*/
|
||||||
function sourceItems() {
|
function sourceItems() {
|
||||||
|
// get items (this may actually be a DataObjectSet)
|
||||||
|
$items = clone $this->getDataList();
|
||||||
|
|
||||||
|
// TODO: Sorting could be implemented on regular DataObjectSets.
|
||||||
|
if(method_exists($items,'canSortBy') && isset($_REQUEST['ctf'][$this->Name()]['sort'])) {
|
||||||
|
$sort = $_REQUEST['ctf'][$this->Name()]['sort'];
|
||||||
|
// TODO: sort direction
|
||||||
|
if($items->canSortBy($sort)) $items = $items->sort($sort);
|
||||||
|
}
|
||||||
|
|
||||||
// Determine pagination limit, offset
|
// Determine pagination limit, offset
|
||||||
$SQL_limit = ($this->showPagination && $this->pageSize) ? "{$this->pageSize}" : null;
|
// To disable pagination, set $this->showPagination to false.
|
||||||
if(isset($_REQUEST['ctf'][$this->Name()]['start']) && is_numeric($_REQUEST['ctf'][$this->Name()]['start'])) {
|
if($this->showPagination && $this->pageSize) {
|
||||||
$SQL_start = (isset($_REQUEST['ctf'][$this->Name()]['start'])) ? intval($_REQUEST['ctf'][$this->Name()]['start']) : "0";
|
$SQL_limit = (int)$this->pageSize;
|
||||||
} else {
|
if(isset($_REQUEST['ctf'][$this->Name()]['start']) && is_numeric($_REQUEST['ctf'][$this->Name()]['start'])) {
|
||||||
$SQL_start = 0;
|
$SQL_start = (isset($_REQUEST['ctf'][$this->Name()]['start'])) ? intval($_REQUEST['ctf'][$this->Name()]['start']) : "0";
|
||||||
}
|
} else {
|
||||||
|
$SQL_start = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Custom source items can be explicitly passed
|
$items = $items->getRange($SQL_start, $SQL_limit);
|
||||||
if(isset($this->customSourceItems)) {
|
}
|
||||||
if($this->showPagination && $this->pageSize) {
|
|
||||||
$items = $this->customSourceItems->getRange($SQL_start, $SQL_limit);
|
|
||||||
} else {
|
|
||||||
$items = $this->customSourceItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise we use the internal data list
|
|
||||||
} else {
|
|
||||||
// get the DataList of items
|
|
||||||
$items = $this->getDataList();
|
|
||||||
|
|
||||||
// we don't limit when doing certain actions T
|
|
||||||
$methodName = isset($_REQUEST['url']) ? array_pop(explode('/', $_REQUEST['url'])) : null;
|
|
||||||
if(!$methodName || !in_array($methodName,array('printall','export'))) {
|
|
||||||
$items->limit(array(
|
|
||||||
'limit' => $SQL_limit,
|
|
||||||
'start' => (isset($SQL_start)) ? $SQL_start : null
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $items;
|
return $items;
|
||||||
}
|
}
|
||||||
@ -458,12 +448,9 @@ JS
|
|||||||
* Returns the DataList for this field.
|
* Returns the DataList for this field.
|
||||||
*/
|
*/
|
||||||
function getDataList() {
|
function getDataList() {
|
||||||
// Load the data from the form
|
// If we weren't passed in a DataList to begin with, try and get the datalist from the form
|
||||||
// Note that this will override any specific. This is so that explicitly-passed sets of
|
if($this->form && $this->getDataListFromForm) {
|
||||||
// parameters that represent a relation can be replaced with the relation itself. This is
|
$this->getDataListFromForm = false;
|
||||||
// a little clumsy and won't work if people have used a field name that is the same as a
|
|
||||||
// relation but have specified alternative parameters.
|
|
||||||
if($this->form) {
|
|
||||||
$relation = $this->name;
|
$relation = $this->name;
|
||||||
if($record = $this->form->getRecord()) {
|
if($record = $this->form->getRecord()) {
|
||||||
if($record->hasMethod($relation)) $this->dataList = $record->$relation();
|
if($record->hasMethod($relation)) $this->dataList = $record->$relation();
|
||||||
@ -474,20 +461,7 @@ JS
|
|||||||
user_error(get_class($this). ' is missing a DataList', E_USER_ERROR);
|
user_error(get_class($this). ' is missing a DataList', E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
$dl = clone $this->dataList;
|
return $this->dataList;
|
||||||
|
|
||||||
if(isset($_REQUEST['ctf'][$this->Name()]['sort'])) {
|
|
||||||
$query = $this->dataList->dataQuery()->query();
|
|
||||||
$SQL_sort = Convert::raw2sql($_REQUEST['ctf'][$this->Name()]['sort']);
|
|
||||||
$sql = $query->sql();
|
|
||||||
// see {isFieldSortable}
|
|
||||||
if(in_array($SQL_sort,$query->select) || stripos($sql,"AS {$SQL_sort}")) {
|
|
||||||
$dl->sort($SQL_sort);
|
|
||||||
}
|
|
||||||
if($query->canSortBy($column)) $query->orderby = $column.' '.$dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $dl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCsvDataList() {
|
function getCsvDataList() {
|
||||||
@ -499,14 +473,20 @@ JS
|
|||||||
* @deprecated Use getDataList() instead.
|
* @deprecated Use getDataList() instead.
|
||||||
*/
|
*/
|
||||||
function getQuery() {
|
function getQuery() {
|
||||||
return $this->getDataList()->dataQuery()->query();
|
$list = $this->getDataList();
|
||||||
|
if(method_exists($list,'dataQuery')) {
|
||||||
|
return $this->getDataList()->dataQuery()->query();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use getCsvDataList() instead.
|
* @deprecated Use getCsvDataList() instead.
|
||||||
*/
|
*/
|
||||||
function getCsvQuery() {
|
function getCsvQuery() {
|
||||||
return $this->getCsvDataList()->dataQuery()->query();
|
$list = $this->getCsvDataList();
|
||||||
|
if(method_exists($list,'dataQuery')) {
|
||||||
|
return $list->dataQuery()->query();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function FieldList() {
|
function FieldList() {
|
||||||
@ -562,8 +542,7 @@ JS
|
|||||||
$childId = Convert::raw2sql($_REQUEST['ctf']['childID']);
|
$childId = Convert::raw2sql($_REQUEST['ctf']['childID']);
|
||||||
|
|
||||||
if (is_numeric($childId)) {
|
if (is_numeric($childId)) {
|
||||||
$childObject = DataObject::get_by_id($this->sourceClass(), $childId);
|
$this->getDataList()->removeById($childId);
|
||||||
if($childObject) $childObject->delete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO return status in JSON etc.
|
// TODO return status in JSON etc.
|
||||||
@ -884,8 +863,19 @@ JS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
private $_cache_TotalCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the total number of items in the source DataList
|
||||||
|
*/
|
||||||
function TotalCount() {
|
function TotalCount() {
|
||||||
return $this->getDataList()->Count();
|
if($this->_cache_TotalCount === null) {
|
||||||
|
$this->_cache_TotalCount = $this->getDataList()->Count();
|
||||||
|
}
|
||||||
|
return $this->_cache_TotalCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -951,6 +941,14 @@ JS
|
|||||||
$now = Date("d-m-Y-H-i");
|
$now = Date("d-m-Y-H-i");
|
||||||
$fileName = "export-$now.csv";
|
$fileName = "export-$now.csv";
|
||||||
|
|
||||||
|
// No pagination for export
|
||||||
|
$oldShowPagination = $this->showPagination;
|
||||||
|
$this->showPagination = false;
|
||||||
|
|
||||||
|
$result = $this->renderWith(array($this->template . '_printable', 'TableListField_printable'));
|
||||||
|
|
||||||
|
$this->showPagination = $oldShowPagination;
|
||||||
|
|
||||||
if($fileData = $this->generateExportFileData($numColumns, $numRows)){
|
if($fileData = $this->generateExportFileData($numColumns, $numRows)){
|
||||||
return SS_HTTPRequest::send_file($fileData, $fileName);
|
return SS_HTTPRequest::send_file($fileData, $fileName);
|
||||||
}else{
|
}else{
|
||||||
@ -1562,42 +1560,11 @@ class TableListField_ItemRequest extends RequestHandler {
|
|||||||
// used to discover fields if requested and for population of field
|
// used to discover fields if requested and for population of field
|
||||||
if(is_numeric($this->itemID)) {
|
if(is_numeric($this->itemID)) {
|
||||||
// we have to use the basedataclass, otherwise we might exclude other subclasses
|
// we have to use the basedataclass, otherwise we might exclude other subclasses
|
||||||
return DataObject::get_by_id(ClassInfo::baseDataClass(Object::getCustomClass($this->ctf->sourceClass())), $this->itemID);
|
return $this->ctf->getDataList()->byId($this->itemID);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the db-fieldname of the currently used has_one-relationship.
|
|
||||||
*/
|
|
||||||
function getParentIdName( $parentClass, $childClass ) {
|
|
||||||
return $this->getParentIdNameRelation( $childClass, $parentClass, 'has_one' );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manually overwrites the parent-ID relations.
|
|
||||||
* @see setParentClass()
|
|
||||||
*
|
|
||||||
* @param String $str Example: FamilyID (when one Individual has_one Family)
|
|
||||||
*/
|
|
||||||
function setParentIdName($str) {
|
|
||||||
$this->parentIdName = $str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the db-fieldname of the currently used relationship.
|
|
||||||
*/
|
|
||||||
function getParentIdNameRelation($parentClass, $childClass, $relation) {
|
|
||||||
if($this->parentIdName) return $this->parentIdName;
|
|
||||||
|
|
||||||
$relations = singleton($parentClass)->$relation();
|
|
||||||
$classes = ClassInfo::ancestry($childClass);
|
|
||||||
foreach($relations as $k => $v) {
|
|
||||||
if(array_key_exists($v, $classes)) return $k . 'ID';
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return TableListField
|
* @return TableListField
|
||||||
*/
|
*/
|
||||||
|
@ -153,7 +153,6 @@ class Group extends DataObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$memberList->setPermissions(array('edit', 'delete', 'export', 'add', 'inlineadd'));
|
$memberList->setPermissions(array('edit', 'delete', 'export', 'add', 'inlineadd'));
|
||||||
$memberList->setParentClass('Group');
|
|
||||||
$memberList->setPopupCaption(_t('SecurityAdmin.VIEWUSER', 'View User'));
|
$memberList->setPopupCaption(_t('SecurityAdmin.VIEWUSER', 'View User'));
|
||||||
|
|
||||||
$fields->push($idField = new HiddenField("ID"));
|
$fields->push($idField = new HiddenField("ID"));
|
||||||
|
@ -100,13 +100,11 @@ class ComplexTableFieldTest_Controller extends Controller {
|
|||||||
$playersField = new ComplexTableField(
|
$playersField = new ComplexTableField(
|
||||||
$this,
|
$this,
|
||||||
'Players',
|
'Players',
|
||||||
'ComplexTableFieldTest_Player',
|
$team->Players(),
|
||||||
ComplexTableFieldTest_Player::$summary_fields,
|
ComplexTableFieldTest_Player::$summary_fields,
|
||||||
'getCMSFields'
|
'getCMSFields'
|
||||||
);
|
);
|
||||||
|
|
||||||
$playersField->setParentClass('ComplexTableFieldTest_Team');
|
|
||||||
|
|
||||||
$form = new Form(
|
$form = new Form(
|
||||||
$this,
|
$this,
|
||||||
'ManyManyForm',
|
'ManyManyForm',
|
||||||
@ -131,13 +129,11 @@ class ComplexTableFieldTest_Controller extends Controller {
|
|||||||
$sponsorsField = new ComplexTableField(
|
$sponsorsField = new ComplexTableField(
|
||||||
$this,
|
$this,
|
||||||
'Sponsors',
|
'Sponsors',
|
||||||
'ComplexTableFieldTest_Sponsor',
|
$team->Sponsors(),
|
||||||
ComplexTableFieldTest_Sponsor::$summary_fields,
|
ComplexTableFieldTest_Sponsor::$summary_fields,
|
||||||
'getCMSFields'
|
'getCMSFields'
|
||||||
);
|
);
|
||||||
|
|
||||||
$sponsorsField->setParentClass('ComplexTableFieldTest_Team');
|
|
||||||
|
|
||||||
$form = new Form(
|
$form = new Form(
|
||||||
$this,
|
$this,
|
||||||
'HasManyForm',
|
'HasManyForm',
|
||||||
|
@ -292,6 +292,38 @@ class TableListFieldTest extends SapphireTest {
|
|||||||
|
|
||||||
unset($_REQUEST['ctf']);
|
unset($_REQUEST['ctf']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that a DataObjectSet can be passed to TableListField
|
||||||
|
*/
|
||||||
|
function testDataObjectSet() {
|
||||||
|
$one = new TableListFieldTest_Obj;
|
||||||
|
$one->A = "A-one";
|
||||||
|
$two = new TableListFieldTest_Obj;
|
||||||
|
$two->A = "A-two";
|
||||||
|
$three = new TableListFieldTest_Obj;
|
||||||
|
$three->A = "A-three";
|
||||||
|
|
||||||
|
$list = new DataObjectSet($one, $two, $three);
|
||||||
|
|
||||||
|
// A TableListField must be inside a form for its links to be generated
|
||||||
|
$form = new Form(new TableListFieldTest_TestController(), "TestForm", new FieldSet(
|
||||||
|
new TableListField("Tester", $list, array(
|
||||||
|
"A" => "Col A",
|
||||||
|
"B" => "Col B",
|
||||||
|
"C" => "Col C",
|
||||||
|
"D" => "Col D",
|
||||||
|
"E" => "Col E",
|
||||||
|
))
|
||||||
|
), new FieldSet());
|
||||||
|
|
||||||
|
$table = $form->dataFieldByName('Tester');
|
||||||
|
$rendered = $table->FieldHolder();
|
||||||
|
|
||||||
|
$this->assertContains('A-one', $rendered);
|
||||||
|
$this->assertContains('A-two', $rendered);
|
||||||
|
$this->assertContains('A-three', $rendered);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TableListFieldTest_Obj extends DataObject implements TestOnly {
|
class TableListFieldTest_Obj extends DataObject implements TestOnly {
|
||||||
|
Loading…
Reference in New Issue
Block a user