mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
ENHANCEMENT: Refactored TableListField and subclasses to rely on the DataList to handle data manipulatation.
API CHANGE: A DataList can be passed as the 2nd argument to the constructor; this is the recommended approach for editing non-relations. API CHANGE: You can't set a custom query; only a custom DataList. API CHANGE: You can't have one of these fields editing data that doesn't correspond to a DataList - there must be some kind of DataObject behind it. API CHANGE: If the field's name corresponds to a relation on the object being edited, then the relation is used as the data set - all the source* parameters are ignored. API CHANGE: relationAutoSetting only works if your form has had the corresponding data object loaded with $form->loadDataFrom(). API CHANGE: relationAutoSetting can't be turned off; attach a non-relation DataList instead.
This commit is contained in:
parent
165f38361b
commit
319d2f4952
@ -104,12 +104,15 @@ class MemberTableField extends ComplexTableField {
|
||||
}
|
||||
|
||||
if($this->group) {
|
||||
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\"";
|
||||
|
@ -39,7 +39,7 @@ class ComplexTableField extends TableListField {
|
||||
|
||||
protected $detailFormFields;
|
||||
|
||||
protected $viewAction, $sourceJoin, $sourceItems;
|
||||
protected $viewAction;
|
||||
|
||||
/**
|
||||
* @var Controller
|
||||
@ -119,14 +119,6 @@ class ComplexTableField extends TableListField {
|
||||
*/
|
||||
protected $detailFormValidator = null;
|
||||
|
||||
/**
|
||||
* Automatically detect a has-one relationship
|
||||
* in the popup (=child-class) and save the relation ID.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $relationAutoSetting = true;
|
||||
|
||||
/**
|
||||
* Default size for the popup box
|
||||
*/
|
||||
@ -210,31 +202,6 @@ class ComplexTableField extends TableListField {
|
||||
parent::__construct($name, $sourceClass, $fieldList, $sourceFilter, $sourceSort, $sourceJoin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the record filter for this table.
|
||||
* It will automatically add a relation filter if relationAutoSetting is true, and it can determine an appropriate
|
||||
* filter.
|
||||
*/
|
||||
function sourceFilter() {
|
||||
$sourceFilter = parent::sourceFilter();
|
||||
|
||||
if($this->relationAutoSetting
|
||||
&& $this->getParentClass()
|
||||
&& ($filterKey = $this->getParentIdName($this->getParentClass(), $this->sourceClass()))
|
||||
&& ($filterValue = $this->sourceID()) ) {
|
||||
|
||||
$newFilter = "\"$filterKey\" = '" . Convert::raw2sql($filterValue) . "'";
|
||||
|
||||
if($sourceFilter && is_array($sourceFilter)) {
|
||||
// Note that the brackets below are taken into account when building this
|
||||
$sourceFilter = implode(") AND (", $sourceFilter);
|
||||
}
|
||||
|
||||
$sourceFilter = $sourceFilter ? "($sourceFilter) AND ($newFilter)" : $newFilter;
|
||||
}
|
||||
return $sourceFilter;
|
||||
}
|
||||
|
||||
function isComposite() {
|
||||
return false;
|
||||
}
|
||||
@ -277,26 +244,22 @@ JS;
|
||||
return $this->renderWith($this->template);
|
||||
}
|
||||
|
||||
function sourceClass() {
|
||||
return $this->sourceClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DataObjectSet
|
||||
*/
|
||||
function Items() {
|
||||
$this->sourceItems = $this->sourceItems();
|
||||
$sourceItems = $this->sourceItems();
|
||||
|
||||
if(!$this->sourceItems) {
|
||||
if(!$sourceItems) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$pageStart = (isset($_REQUEST['ctf'][$this->Name()]['start']) && is_numeric($_REQUEST['ctf'][$this->Name()]['start'])) ? $_REQUEST['ctf'][$this->Name()]['start'] : 0;
|
||||
$this->sourceItems->setPageLimits($pageStart, $this->pageSize, $this->totalCount);
|
||||
$sourceItems->setPageLimits($pageStart, $this->pageSize, $this->totalCount);
|
||||
|
||||
$output = new DataObjectSet();
|
||||
foreach($this->sourceItems as $pageIndex=>$item) {
|
||||
$output->push(new $this->itemClass($item, $this));
|
||||
foreach($sourceItems as $pageIndex=>$item) {
|
||||
$output->push(Object::create($this->itemClass,$item, $this, $pageStart+$pageIndex));
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
@ -547,27 +510,12 @@ JS;
|
||||
|
||||
if($this->getParentClass()) {
|
||||
$detailFields->push(new HiddenField('ctf[parentClass]', '', $this->getParentClass()));
|
||||
|
||||
if($manyManyRelationName && $this->relationAutoSetting) {
|
||||
$detailFields->push(new HiddenField('ctf[manyManyRelation]', '', $manyManyRelationName));
|
||||
}
|
||||
|
||||
if($hasManyRelationName && $this->relationAutoSetting) {
|
||||
$detailFields->push(new HiddenField('ctf[hasManyRelation]', '', $hasManyRelationName));
|
||||
}
|
||||
|
||||
if($manyManyRelationName || $hasManyRelationName) {
|
||||
$detailFields->push(new HiddenField('ctf[sourceID]', '', $this->sourceID()));
|
||||
}
|
||||
|
||||
// Hack for model admin: model admin will have included a dropdown for the relation itself
|
||||
$parentIdName = $this->getParentIdName($this->getParentClass(), $this->sourceClass());
|
||||
|
||||
if($parentIdName) {
|
||||
if($this->relationAutoSetting) {
|
||||
// Hack for model admin: model admin will have included a dropdown for the relation itself
|
||||
$detailFields->removeByName($parentIdName);
|
||||
$detailFields->push(new HiddenField($parentIdName, '', $this->sourceID()));
|
||||
}
|
||||
$detailFields->removeByName($parentIdName);
|
||||
$detailFields->push(new HiddenField($parentIdName, '', $this->sourceID()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -614,16 +562,10 @@ JS;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, a ComplexTableField will assume that the field name is the name of a has-many relation on the object being
|
||||
* edited. It will identify the foreign key in the object being listed, and filter on that column, as well as auto-setting
|
||||
* that column for newly created records.
|
||||
*
|
||||
* Calling $this->setRelationAutoSetting(false) will disable this functionality.
|
||||
*
|
||||
* @param boolean $value Should the relation auto-setting functionality be enabled?
|
||||
* @deprecated
|
||||
*/
|
||||
function setRelationAutoSetting($value) {
|
||||
$this->relationAutoSetting = $value;
|
||||
user_error("ComplexTableField::setRelationAutoSetting() is deprecated; manipulate the DataList instead", E_USER_WARNING);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -648,21 +590,8 @@ JS;
|
||||
return Director::redirectBack();
|
||||
}
|
||||
|
||||
// Save the many many relationship if it's available
|
||||
if(isset($data['ctf']['manyManyRelation'])) {
|
||||
$parentRecord = DataObject::get_by_id($data['ctf']['parentClass'], (int) $data['ctf']['sourceID']);
|
||||
$relationName = $data['ctf']['manyManyRelation'];
|
||||
$componentSet = $parentRecord ? $parentRecord->getManyManyComponents($relationName) : null;
|
||||
if($componentSet) $componentSet->add($childData);
|
||||
}
|
||||
|
||||
if(isset($data['ctf']['hasManyRelation'])) {
|
||||
$parentRecord = DataObject::get_by_id($data['ctf']['parentClass'], (int) $data['ctf']['sourceID']);
|
||||
$relationName = $data['ctf']['hasManyRelation'];
|
||||
|
||||
$componentSet = $parentRecord ? $parentRecord->getComponents($relationName) : null;
|
||||
if($componentSet) $componentSet->add($childData);
|
||||
}
|
||||
// Save this item into the given relationship
|
||||
$this->getDataList()->add($childData);
|
||||
|
||||
$referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null;
|
||||
|
||||
@ -830,14 +759,9 @@ class ComplexTableField_ItemRequest extends TableListField_ItemRequest {
|
||||
$form->sessionMessage($e->getResult()->message(), 'bad');
|
||||
return Director::redirectBack();
|
||||
}
|
||||
|
||||
// Save the many many relationship if it's available
|
||||
if(isset($data['ctf']['manyManyRelation'])) {
|
||||
$parentRecord = DataObject::get_by_id($data['ctf']['parentClass'], (int) $data['ctf']['sourceID']);
|
||||
$relationName = $data['ctf']['manyManyRelation'];
|
||||
$componentSet = $parentRecord->getManyManyComponents($relationName);
|
||||
$componentSet->add($dataObject);
|
||||
}
|
||||
|
||||
// Save this item into the given relationship
|
||||
$this->ctf->getDataList()->add($childData);
|
||||
|
||||
$referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null;
|
||||
|
||||
|
@ -118,14 +118,12 @@ class FormScaffolder extends Object {
|
||||
);
|
||||
}
|
||||
$relationshipFields = singleton($component)->summaryFields();
|
||||
$foreignKey = $this->obj->getRemoteJoinField($relationship);
|
||||
$ctf = new ComplexTableField(
|
||||
$this,
|
||||
$relationship,
|
||||
$component,
|
||||
null,
|
||||
$relationshipFields,
|
||||
"getCMSFields",
|
||||
"\"$foreignKey\" = " . $this->obj->ID
|
||||
"getCMSFields"
|
||||
);
|
||||
$ctf->setPermissions(TableListField::permissions_for_object($component));
|
||||
if($this->tabbed) {
|
||||
@ -146,17 +144,12 @@ class FormScaffolder extends Object {
|
||||
}
|
||||
|
||||
$relationshipFields = singleton($component)->summaryFields();
|
||||
$filterWhere = $this->obj->getManyManyFilter($relationship, $component);
|
||||
$filterJoin = $this->obj->getManyManyJoin($relationship, $component);
|
||||
$ctf = new ComplexTableField(
|
||||
$this,
|
||||
$relationship,
|
||||
$component,
|
||||
null,
|
||||
$relationshipFields,
|
||||
"getCMSFields",
|
||||
$filterWhere,
|
||||
'',
|
||||
$filterJoin
|
||||
"getCMSFields"
|
||||
);
|
||||
$ctf->setPermissions(TableListField::permissions_for_object($component));
|
||||
$ctf->popupClass = "ScaffoldingComplexTableField_Popup";
|
||||
|
@ -28,10 +28,6 @@
|
||||
|
||||
class TableField extends TableListField {
|
||||
|
||||
protected $sourceClass;
|
||||
|
||||
protected $sourceFilter;
|
||||
|
||||
protected $fieldList;
|
||||
|
||||
/**
|
||||
@ -52,10 +48,6 @@ class TableField extends TableListField {
|
||||
* preset relations or other default data.
|
||||
*/
|
||||
protected $fieldTypes;
|
||||
|
||||
protected $sourceSort;
|
||||
|
||||
protected $sourceJoin;
|
||||
|
||||
/**
|
||||
* @var $template string Template-Overrides
|
||||
@ -105,8 +97,6 @@ class TableField extends TableListField {
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $relationAutoSetting = true;
|
||||
|
||||
function __construct($name, $sourceClass, $fieldList = null, $fieldTypes, $filterField = null,
|
||||
$sourceFilter = null, $editExisting = true, $sourceSort = null, $sourceJoin = null) {
|
||||
|
||||
@ -174,6 +164,9 @@ class TableField extends TableListField {
|
||||
$rows = $this->sortData(ArrayLib::invert($this->value));
|
||||
// ignore all rows which are already saved
|
||||
if(isset($rows['new'])) {
|
||||
if($sourceItems instanceof DataList) $sourceItems = $sourceItems->toDataObjectSet();
|
||||
|
||||
|
||||
$newRows = $this->sortData($rows['new']);
|
||||
// iterate over each value (not each row)
|
||||
$i = 0;
|
||||
@ -189,7 +182,7 @@ class TableField extends TableListField {
|
||||
}
|
||||
|
||||
// generate a temporary DataObject container (not saved in the database)
|
||||
$sourceClass = $this->sourceClass;
|
||||
$sourceClass = $this->sourceClass();
|
||||
$sourceItems->push(new $sourceClass($newRow));
|
||||
|
||||
$i++;
|
||||
@ -264,17 +257,10 @@ class TableField extends TableListField {
|
||||
$savedObjIds = $this->saveData($newFields,false);
|
||||
}
|
||||
|
||||
// Optionally save the newly created records into a relationship
|
||||
// on $record. This assumes the name of this formfield instance
|
||||
// is set to a relationship name on $record.
|
||||
if($this->relationAutoSetting) {
|
||||
$relationName = $this->Name();
|
||||
if($record->has_many($relationName) || $record->many_many($relationName)) {
|
||||
if($savedObjIds) foreach($savedObjIds as $id => $status) {
|
||||
$record->$relationName()->add($id);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add the new records to the DataList
|
||||
if($savedObjIds) foreach($savedObjIds as $id => $status) {
|
||||
$this->getDataList()->add($id);
|
||||
}
|
||||
|
||||
// Update the internal source items cache
|
||||
$this->value = null;
|
||||
@ -386,9 +372,9 @@ class TableField extends TableListField {
|
||||
|
||||
// either look for an existing object, or create a new one
|
||||
if($existingValues) {
|
||||
$obj = DataObject::get_by_id($this->sourceClass, $objectid);
|
||||
$obj = DataObject::get_by_id($this->sourceClass(), $objectid);
|
||||
} else {
|
||||
$sourceClass = $this->sourceClass;
|
||||
$sourceClass = $this->sourceClass();
|
||||
$obj = new $sourceClass();
|
||||
}
|
||||
|
||||
@ -490,13 +476,6 @@ class TableField extends TableListField {
|
||||
|
||||
return $this->renderWith($this->template);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Int
|
||||
*/
|
||||
function sourceID() {
|
||||
return $this->filterField;
|
||||
}
|
||||
|
||||
function setTransformationConditions($conditions) {
|
||||
$this->transformationConditions = $conditions;
|
||||
@ -601,20 +580,6 @@ JS;
|
||||
function setRequiredFields($fields) {
|
||||
$this->requiredFields = $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $value
|
||||
*/
|
||||
function setRelationAutoSetting($value) {
|
||||
$this->relationAutoSetting = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
function getRelationAutoSetting() {
|
||||
return $this->relationAutoSetting;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,19 +21,10 @@
|
||||
* @subpackage fields-relational
|
||||
*/
|
||||
class TableListField extends FormField {
|
||||
|
||||
/**
|
||||
* @var $cachedSourceItems DataObjectSet Prevent {@sourceItems()} from being called multiple times.
|
||||
* The {@link DataList} object defining the source data for this view/
|
||||
*/
|
||||
protected $cachedSourceItems;
|
||||
|
||||
protected $sourceClass;
|
||||
|
||||
protected $sourceFilter = "";
|
||||
|
||||
protected $sourceSort = "";
|
||||
|
||||
protected $sourceJoin = array();
|
||||
protected $dataList;
|
||||
|
||||
protected $fieldList;
|
||||
|
||||
@ -137,14 +128,6 @@ class TableListField extends FormField {
|
||||
* Mostly needed in ComplexTableField-subclass.
|
||||
*/
|
||||
public $defaultAction = '';
|
||||
|
||||
/**
|
||||
* @var $customQuery Specify custom query, e.g. for complicated having/groupby-constructs.
|
||||
* Caution: TableListField automatically selects the ID from the {@sourceClass}, because it relies
|
||||
* on this information e.g. in saving a TableField. Please use a custom select if you want to filter
|
||||
* for other IDs in joined tables: $query->select[] = "MyJoinedTable.ID AS MyJoinedTableID"
|
||||
*/
|
||||
protected $customQuery;
|
||||
|
||||
/**
|
||||
* @var $customCsvQuery Query for CSV-export (might need different fields or further filtering)
|
||||
@ -257,26 +240,27 @@ class TableListField extends FormField {
|
||||
|
||||
protected $__cachedQuery;
|
||||
|
||||
function __construct($name, $sourceClass, $fieldList = null, $sourceFilter = null,
|
||||
function __construct($name, $sourceClass = null, $fieldList = null, $sourceFilter = null,
|
||||
$sourceSort = null, $sourceJoin = null) {
|
||||
|
||||
$this->fieldList = ($fieldList) ? $fieldList : singleton($sourceClass)->summaryFields();
|
||||
$this->sourceClass = $sourceClass;
|
||||
$this->sourceFilter = $sourceFilter;
|
||||
$this->sourceSort = $sourceSort;
|
||||
$this->sourceJoin = $sourceJoin;
|
||||
|
||||
if($sourceClass) {
|
||||
// You can optionally pass a DataList as the 2nd argument to the constructor
|
||||
if($sourceClass instanceof DataList) {
|
||||
$this->dataList = $sourceClass;
|
||||
|
||||
} else {
|
||||
$this->dataList = DataObject::get($sourceClass)->filter($sourceFilter)
|
||||
->sort($sourceSort)->join($sourceJoin);
|
||||
}
|
||||
}
|
||||
|
||||
$this->readOnly = false;
|
||||
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filter
|
||||
*/
|
||||
function sourceFilter() {
|
||||
return $this->sourceFilter;
|
||||
}
|
||||
|
||||
function index() {
|
||||
return $this->FieldHolder();
|
||||
}
|
||||
@ -287,7 +271,7 @@ class TableListField extends FormField {
|
||||
);
|
||||
|
||||
function sourceClass() {
|
||||
return $this->sourceClass;
|
||||
return $this->getDataList()->dataClass();
|
||||
}
|
||||
|
||||
function handleItem($request) {
|
||||
@ -351,7 +335,7 @@ JS
|
||||
|
||||
$headings[] = new ArrayData(array(
|
||||
"Name" => $fieldName,
|
||||
"Title" => ($this->sourceClass) ? singleton($this->sourceClass)->fieldLabel($fieldTitle) : $fieldTitle,
|
||||
"Title" => ($this->sourceClass()) ? singleton($this->sourceClass())->fieldLabel($fieldTitle) : $fieldTitle,
|
||||
"IsSortable" => $isSortable,
|
||||
"SortLink" => $sortLink,
|
||||
"SortBy" => $isSorted,
|
||||
@ -403,27 +387,16 @@ JS
|
||||
/**
|
||||
* Provide a custom query to compute sourceItems. This is the preferred way to using
|
||||
* {@setSourceItems}, because we can still paginate.
|
||||
* Caution: Other parameters such as {@sourceFilter} will be ignored.
|
||||
* Please use this only as a fallback for really complex queries (e.g. involving HAVING and GROUPBY).
|
||||
*
|
||||
* @param $query SS_Query
|
||||
* @param $query DataList
|
||||
*/
|
||||
function setCustomQuery(SQLQuery $query) {
|
||||
// The type-hinting above doesn't seem to work consistently
|
||||
if($query instanceof SQLQuery) {
|
||||
$this->customQuery = $query;
|
||||
} else {
|
||||
user_error('TableList::setCustomQuery() should be passed a SQLQuery', E_USER_WARNING);
|
||||
}
|
||||
function setCustomQuery(DataList $dataList) {
|
||||
$this->dataList = $dataList;
|
||||
}
|
||||
|
||||
function setCustomCsvQuery(SQLQuery $query) {
|
||||
// The type-hinting above doesn't seem to work consistently
|
||||
if($query instanceof SQLQuery) {
|
||||
$this->customCsvQuery = $query;
|
||||
} else {
|
||||
user_error('TableList::setCustomCsvQuery() should be passed a SQLQuery', E_USER_WARNING);
|
||||
}
|
||||
function setCustomCsvQuery(DataList $dataList) {
|
||||
$this->customCsvQuery = $query;
|
||||
}
|
||||
|
||||
function setCustomSourceItems(DataObjectSet $items) {
|
||||
@ -436,45 +409,43 @@ JS
|
||||
}
|
||||
|
||||
function sourceItems() {
|
||||
// Determine pagination limit, offset
|
||||
$SQL_limit = ($this->showPagination && $this->pageSize) ? "{$this->pageSize}" : null;
|
||||
if(isset($_REQUEST['ctf'][$this->Name()]['start']) && is_numeric($_REQUEST['ctf'][$this->Name()]['start'])) {
|
||||
$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
|
||||
if(isset($this->customSourceItems)) {
|
||||
if($this->showPagination && $this->pageSize) {
|
||||
$items = $this->customSourceItems->getRange($SQL_start, $SQL_limit);
|
||||
} else {
|
||||
$items = $this->customSourceItems;
|
||||
}
|
||||
} elseif(isset($this->cachedSourceItems)) {
|
||||
$items = $this->cachedSourceItems;
|
||||
|
||||
// Otherwise we use the internal data list
|
||||
} else {
|
||||
// get query
|
||||
$dataQuery = $this->getQuery();
|
||||
// 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'))) {
|
||||
$dataQuery->limit(array(
|
||||
$items->limit(array(
|
||||
'limit' => $SQL_limit,
|
||||
'start' => (isset($SQL_start)) ? $SQL_start : null
|
||||
));
|
||||
}
|
||||
|
||||
// get data
|
||||
$records = $dataQuery->execute();
|
||||
$sourceClass = $this->sourceClass;
|
||||
$dataobject = new $sourceClass();
|
||||
$items = $dataobject->buildDataObjectSet($records, 'DataObjectSet');
|
||||
|
||||
$this->cachedSourceItems = $items;
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a DataObjectSet of TableListField_Item objects, suitable for display in the template.
|
||||
*/
|
||||
function Items() {
|
||||
$fieldItems = new DataObjectSet();
|
||||
if($items = $this->sourceItems()) foreach($items as $item) {
|
||||
@ -484,16 +455,19 @@ JS
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the query for sourceitems (without pagination/limit-clause)
|
||||
*
|
||||
* @return string
|
||||
* Returns the DataList for this field.
|
||||
*/
|
||||
function getQuery() {
|
||||
if($this->customQuery) {
|
||||
$query = clone $this->customQuery;
|
||||
$baseClass = ClassInfo::baseDataClass($this->sourceClass);
|
||||
} else {
|
||||
$query = singleton($this->sourceClass)->extendedSQL($this->sourceFilter(), $this->sourceSort, null, $this->sourceJoin);
|
||||
function getDataList() {
|
||||
// Load the data from the form
|
||||
// Note that this will override any specific. This is so that explicitly-passed sets of
|
||||
// parameters that represent a relation can be replaced with the relation itself. This is
|
||||
// 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;
|
||||
if($record = $this->form->getRecord()) {
|
||||
if($record->hasMethod($relation)) $this->dataList = $record->$relation();
|
||||
}
|
||||
}
|
||||
|
||||
if(!$this->dataList) {
|
||||
@ -513,20 +487,28 @@ JS
|
||||
if($query->canSortBy($column)) $query->orderby = $column.' '.$dir;
|
||||
}
|
||||
|
||||
return $query;
|
||||
return $dl;
|
||||
}
|
||||
|
||||
function getCsvQuery() {
|
||||
$baseClass = ClassInfo::baseDataClass($this->sourceClass);
|
||||
if($this->customCsvQuery || $this->customQuery) {
|
||||
$query = $this->customCsvQuery ? $this->customCsvQuery : $this->customQuery;
|
||||
} else {
|
||||
$query = singleton($this->sourceClass)->extendedSQL($this->sourceFilter(), $this->sourceSort, null, $this->sourceJoin);
|
||||
}
|
||||
|
||||
return clone $query;
|
||||
function getCsvDataList() {
|
||||
if($this->customCsvQuery) return $this->customCsvQuery;
|
||||
else return $this->getDataList();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use getDataList() instead.
|
||||
*/
|
||||
function getQuery() {
|
||||
return $this->getDataList()->dataQuery()->query();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use getCsvDataList() instead.
|
||||
*/
|
||||
function getCsvQuery() {
|
||||
return $this->getCsvDataList()->dataQuery()->query();
|
||||
}
|
||||
|
||||
function FieldList() {
|
||||
return $this->fieldList;
|
||||
}
|
||||
@ -580,7 +562,7 @@ JS
|
||||
$childId = Convert::raw2sql($_REQUEST['ctf']['childID']);
|
||||
|
||||
if (is_numeric($childId)) {
|
||||
$childObject = DataObject::get_by_id($this->sourceClass, $childId);
|
||||
$childObject = DataObject::get_by_id($this->sourceClass(), $childId);
|
||||
if($childObject) $childObject->delete();
|
||||
}
|
||||
|
||||
@ -903,19 +885,10 @@ JS
|
||||
}
|
||||
|
||||
function TotalCount() {
|
||||
if($this->totalCount) {
|
||||
return $this->totalCount;
|
||||
}
|
||||
if($this->customSourceItems) {
|
||||
return $this->customSourceItems->Count();
|
||||
}
|
||||
|
||||
$this->totalCount = $this->getQuery()->unlimitedRowCount();
|
||||
return $this->totalCount;
|
||||
return $this->getDataList()->Count();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* #################################
|
||||
* Search
|
||||
@ -1158,19 +1131,19 @@ JS
|
||||
// adding this to TODO probably add a method to the classes
|
||||
// to return they're translated string
|
||||
// added by ruibarreiros @ 27/11/2007
|
||||
return $this->sourceClass ? singleton($this->sourceClass)->singular_name() : $this->Name();
|
||||
return $this->sourceClass() ? singleton($this->sourceClass())->singular_name() : $this->Name();
|
||||
}
|
||||
|
||||
function NameSingular() {
|
||||
// same as Title()
|
||||
// added by ruibarreiros @ 27/11/2007
|
||||
return $this->sourceClass ? singleton($this->sourceClass)->singular_name() : $this->Name();
|
||||
return $this->sourceClass() ? singleton($this->sourceClass())->singular_name() : $this->Name();
|
||||
}
|
||||
|
||||
function NamePlural() {
|
||||
// same as Title()
|
||||
// added by ruibarreiros @ 27/11/2007
|
||||
return $this->sourceClass ? singleton($this->sourceClass)->plural_name() : $this->Name();
|
||||
return $this->sourceClass() ? singleton($this->sourceClass())->plural_name() : $this->Name();
|
||||
}
|
||||
|
||||
function setTemplate($template) {
|
||||
|
@ -118,6 +118,7 @@ class ComplexTableFieldTest_Controller extends Controller {
|
||||
new FormAction('doSubmit', 'Submit')
|
||||
)
|
||||
);
|
||||
$form->loadDataFrom($team);
|
||||
|
||||
$form->disableSecurityToken();
|
||||
|
||||
@ -148,6 +149,7 @@ class ComplexTableFieldTest_Controller extends Controller {
|
||||
new FormAction('doSubmit', 'Submit')
|
||||
)
|
||||
);
|
||||
$form->loadDataFrom($team);
|
||||
|
||||
$form->disableSecurityToken();
|
||||
|
||||
|
@ -6,6 +6,7 @@ ComplexTableFieldTest_Player:
|
||||
ComplexTableFieldTest_Team:
|
||||
t1:
|
||||
Name: The Awesome People
|
||||
Players: =>ComplexTableFieldTest_Player.p1,=>ComplexTableFieldTest_Player.p2
|
||||
t2:
|
||||
Name: Incredible Four
|
||||
ComplexTableFieldTest_Sponsor:
|
||||
|
@ -20,6 +20,9 @@ class FormScaffolderTest extends SapphireTest {
|
||||
|
||||
function testGetCMSFieldsSingleton() {
|
||||
$fields = singleton('FormScaffolderTest_Article')->getCMSFields();
|
||||
$form = new Form(new Controller(), 'TestForm', $fields, new FieldSet());
|
||||
$form->loadDataFrom(singleton('FormScaffolderTest_Article'));
|
||||
|
||||
$this->assertTrue($fields->hasTabSet(), 'getCMSFields() produces a TabSet');
|
||||
$this->assertNotNull($fields->dataFieldByName('Title'), 'getCMSFields() includes db fields');
|
||||
$this->assertNotNull($fields->dataFieldByName('Content'), 'getCMSFields() includes db fields');
|
||||
@ -29,14 +32,22 @@ class FormScaffolderTest extends SapphireTest {
|
||||
|
||||
function testGetCMSFieldsInstance() {
|
||||
$article1 = $this->objFromFixture('FormScaffolderTest_Article', 'article1');
|
||||
|
||||
$fields = $article1->getCMSFields();
|
||||
$form = new Form(new Controller(), 'TestForm', $fields, new FieldSet());
|
||||
$form->loadDataFrom($article1);
|
||||
|
||||
$this->assertNotNull($fields->dataFieldByName('AuthorID'), 'getCMSFields() includes has_one fields on instances');
|
||||
$this->assertNotNull($fields->dataFieldByName('Tags'), 'getCMSFields() includes many_many fields if ID is present on instances');
|
||||
}
|
||||
|
||||
function testUpdateCMSFields() {
|
||||
$article1 = $this->objFromFixture('FormScaffolderTest_Article', 'article1');
|
||||
|
||||
$fields = $article1->getCMSFields();
|
||||
$form = new Form(new Controller(), 'TestForm', $fields, new FieldSet());
|
||||
$form->loadDataFrom($article1);
|
||||
|
||||
$this->assertNotNull(
|
||||
$fields->dataFieldByName('AddedExtensionField'),
|
||||
'getCMSFields() includes extended fields'
|
||||
@ -45,18 +56,26 @@ class FormScaffolderTest extends SapphireTest {
|
||||
|
||||
function testRestrictCMSFields() {
|
||||
$article1 = $this->objFromFixture('FormScaffolderTest_Article', 'article1');
|
||||
|
||||
$fields = $article1->scaffoldFormFields(array(
|
||||
'restrictFields' => array('Title')
|
||||
));
|
||||
$form = new Form(new Controller(), 'TestForm', $fields, new FieldSet());
|
||||
$form->loadDataFrom($article1);
|
||||
|
||||
$this->assertNotNull($fields->dataFieldByName('Title'), 'scaffoldCMSFields() includes explitly defined "restrictFields"');
|
||||
$this->assertNull($fields->dataFieldByName('Content'), 'getCMSFields() doesnt include fields left out in a "restrictFields" definition');
|
||||
}
|
||||
|
||||
function testFieldClassesOnGetCMSFields() {
|
||||
$article1 = $this->objFromFixture('FormScaffolderTest_Article', 'article1');
|
||||
|
||||
$fields = $article1->scaffoldFormFields(array(
|
||||
'fieldClasses' => array('Title' => 'HtmlEditorField')
|
||||
));
|
||||
$form = new Form(new Controller(), 'TestForm', $fields, new FieldSet());
|
||||
$form->loadDataFrom($article1);
|
||||
|
||||
$this->assertNotNull(
|
||||
$fields->dataFieldByName('Title')
|
||||
);
|
||||
@ -69,6 +88,9 @@ class FormScaffolderTest extends SapphireTest {
|
||||
|
||||
function testGetFormFields() {
|
||||
$fields = singleton('FormScaffolderTest_Article')->getFrontEndFields();
|
||||
$form = new Form(new Controller(), 'TestForm', $fields, new FieldSet());
|
||||
$form->loadDataFrom(singleton('FormScaffolderTest_Article'));
|
||||
|
||||
$this->assertFalse($fields->hasTabSet(), 'getFrontEndFields() doesnt produce a TabSet by default');
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +166,13 @@ class TableFieldTest extends SapphireTest {
|
||||
$this->assertNotContains($perm1->ID, $tableField->sourceItems()->column('ID'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Relation auto-setting is now the only option
|
||||
*/
|
||||
function testAutoRelationSettingOn() {
|
||||
$o = new TableFieldTest_Object();
|
||||
$o->write();
|
||||
|
||||
$tf = new TableField(
|
||||
'HasManyRelations',
|
||||
'TableFieldTest_HasManyRelation',
|
||||
@ -180,69 +186,16 @@ class TableFieldTest extends SapphireTest {
|
||||
|
||||
// Test with auto relation setting
|
||||
$form = new Form(new TableFieldTest_Controller(), "Form", new FieldSet($tf), new FieldSet());
|
||||
$form->loadDataFrom($o);
|
||||
|
||||
$tf->setValue(array(
|
||||
'new' => array(
|
||||
'Value' => array('one','two',)
|
||||
)
|
||||
));
|
||||
$tf->setRelationAutoSetting(true);
|
||||
$o = new TableFieldTest_Object();
|
||||
$o->write();
|
||||
$form->saveInto($o);
|
||||
$this->assertEquals($o->HasManyRelations()->Count(), 2);
|
||||
}
|
||||
|
||||
function testAutoRelationSettingOff() {
|
||||
$tf = new TableField(
|
||||
'HasManyRelations',
|
||||
'TableFieldTest_HasManyRelation',
|
||||
array(
|
||||
'Value' => 'Value'
|
||||
),
|
||||
array(
|
||||
'Value' => 'TextField'
|
||||
)
|
||||
);
|
||||
|
||||
// Test with auto relation setting
|
||||
$form = new Form(new TableFieldTest_Controller(), "Form", new FieldSet($tf), new FieldSet());
|
||||
$tf->setValue(array(
|
||||
'new' => array(
|
||||
'Value' => array('one','two',)
|
||||
)
|
||||
));
|
||||
$tf->setRelationAutoSetting(false);
|
||||
$o = new TableFieldTest_Object();
|
||||
$o->write();
|
||||
$form->saveInto($o);
|
||||
$this->assertEquals($o->HasManyRelations()->Count(), 0);
|
||||
}
|
||||
|
||||
function testDataValue() {
|
||||
$tf = new TableField(
|
||||
'TestTableField',
|
||||
'TestTableField',
|
||||
array(
|
||||
'Currency' => 'Currency'
|
||||
),
|
||||
array(
|
||||
'Currency' => 'CurrencyField'
|
||||
)
|
||||
);
|
||||
$form = new Form(new TableFieldTest_Controller(), "Form", new FieldSet($tf), new FieldSet());
|
||||
$tf->setValue(array(
|
||||
'new' => array(
|
||||
'Currency' => array(
|
||||
'$1,234.56',
|
||||
'1234.57',
|
||||
)
|
||||
)
|
||||
));
|
||||
$data = $form->getData();
|
||||
|
||||
// @todo Fix getData()
|
||||
//$this->assertEquals($data['TestTableField']['new']['Currency'][0], 1234.56);
|
||||
//$this->assertEquals($data['TestTableField']['new']['Currency'][1], 1234.57);
|
||||
$this->assertEquals(2, $o->HasManyRelations()->Count());
|
||||
}
|
||||
|
||||
function testHasItemsWhenSetAsArray() {
|
||||
|
Loading…
Reference in New Issue
Block a user