mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
mlanthaler: Bugfix: Added isset() to prevent E_NOTICE error.
(merged from branches/gsoc) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@41952 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
b358c50f2f
commit
71f9ac0c10
@ -4,22 +4,22 @@
|
||||
* Provides a tabuar list in your form with view, edit and add links to edit records
|
||||
* with a "has-one"-relationship. Detail-views are shown in a greybox-iframe.
|
||||
* Features pagination in the overview as well as the detail-views.
|
||||
*
|
||||
* CAUTION: You need to make sure that the original form-call to the main controller (e.g. EditForm())
|
||||
* returns a form which includes this field even if no data is loaded,
|
||||
*
|
||||
* CAUTION: You need to make sure that the original form-call to the main controller (e.g. EditForm())
|
||||
* returns a form which includes this field even if no data is loaded,
|
||||
* to provide a "starting point" for action_callfieldmethod and ReferencedField.
|
||||
*
|
||||
*
|
||||
* All URL data sent to and from ComplexTableField is encapsulated in $_REQUEST['ctf']
|
||||
* to avoid side-effects with the main controller.
|
||||
*
|
||||
*
|
||||
* Example-URL for a "DetailForm"-call explained:
|
||||
* "/admin/family/?executeForm=EditForm&action_callfieldmethod&fieldName=Individual&childID=7&methodName=edit"
|
||||
* - executeForm Name of the form on the main rendering page (e.g. "FamilyAdmin")
|
||||
* - action_callfieldmethod Trigger to call a method of a single field in "EditForm" instead of rendering the whole thing
|
||||
* - fieldName Name of the targeted formField
|
||||
* - methodName Method on the formfield (e.g. "ComplexTableField")
|
||||
* - childID Identifier of the database-record (the targeted table is determined by the $sourceClass parameter)
|
||||
*
|
||||
* - childID Identifier of the database-record (the targeted table is determined by the $sourceClass parameter)
|
||||
*
|
||||
* TODO Find a less fragile solution for accessing this field through the main controller and ReferencedField, e.g.
|
||||
* build a seperate CTF-instance (doesn't necessarly have to be connected to the original by ReferencedField)
|
||||
* TODO Control width/height of popup by constructor (hardcoded at the moment)
|
||||
@ -28,19 +28,19 @@
|
||||
* TODO Use automatic has-many and many-many functions to return a ComponentSet rather than building the join manually
|
||||
*/
|
||||
class ComplexTableField extends TableListField {
|
||||
|
||||
|
||||
protected $detailFormFields, $viewAction, $sourceJoin, $sourceItems, $unpagedSourceItems;
|
||||
|
||||
|
||||
/**
|
||||
* @var Controller
|
||||
*/
|
||||
protected $controller;
|
||||
|
||||
|
||||
/**
|
||||
* @var string Classname of the parent-relation to correctly link new records.
|
||||
*/
|
||||
protected $parentClass;
|
||||
|
||||
|
||||
/**
|
||||
* @var array Influence output without having to subclass the template.
|
||||
*/
|
||||
@ -58,9 +58,9 @@ class ComplexTableField extends TableListField {
|
||||
* Template-Overrides
|
||||
*/
|
||||
protected $template = "ComplexTableField";
|
||||
|
||||
|
||||
protected $templatePopup = "ComplexTableField_popup";
|
||||
|
||||
|
||||
/**
|
||||
* @var boolean Trigger pagination (defaults to true for ComplexTableField)
|
||||
*/
|
||||
@ -71,7 +71,7 @@ class ComplexTableField extends TableListField {
|
||||
* This is set by javascript and used by greybox.
|
||||
*/
|
||||
protected $popupCaption = null;
|
||||
|
||||
|
||||
/**
|
||||
* @var $detailFormValidator Validator
|
||||
*/
|
||||
@ -93,7 +93,7 @@ class ComplexTableField extends TableListField {
|
||||
$this->detailFormFields = $detailFormFields;
|
||||
$this->controller = $controller;
|
||||
$this->pageSize = 10;
|
||||
|
||||
|
||||
Requirements::javascript("jsparty/greybox/AmiJS.js");
|
||||
Requirements::javascript("jsparty/greybox/greybox.js");
|
||||
Requirements::javascript('sapphire/javascript/TableListField.js');
|
||||
@ -127,28 +127,28 @@ JS;
|
||||
Requirements::customScript($js);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// compute sourceItems here instead of Items() to ensure that
|
||||
// pagination and filters are respected on template accessors
|
||||
$this->sourceItems();
|
||||
|
||||
return $this->renderWith($this->template);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns non-paginated items.
|
||||
* Please use Items() for pagination.
|
||||
* This function is called whenever a complete result-set is needed,
|
||||
* so even if a single record is displayed in a popup, we need the results
|
||||
* to make pagination work.
|
||||
*
|
||||
*
|
||||
* TODO Merge with more efficient querying of TableListField
|
||||
*/
|
||||
function sourceItems() {
|
||||
if($this->sourceItems) {
|
||||
return $this->sourceItems;
|
||||
}
|
||||
|
||||
|
||||
$limitClause = "";
|
||||
if($this->pageSize) {
|
||||
$limitClause = "{$this->pageSize}";
|
||||
@ -161,44 +161,44 @@ JS;
|
||||
}
|
||||
|
||||
$sourceItems = DataObject::get($this->sourceClass, $this->sourceFilter, $this->sourceSort, $this->sourceJoin, $limitClause);
|
||||
|
||||
|
||||
$this->unpagedSourceItems = DataObject::get($this->sourceClass, $this->sourceFilter, $this->sourceSort, $this->sourceJoin);
|
||||
|
||||
|
||||
$this->totalCount = ($this->unpagedSourceItems) ? $this->unpagedSourceItems->TotalItems() : null;
|
||||
|
||||
|
||||
return $sourceItems;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return DataObjectSet
|
||||
*/
|
||||
function Items() {
|
||||
$this->sourceItems = $this->sourceItems();
|
||||
|
||||
|
||||
if(!$this->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);
|
||||
|
||||
|
||||
$output = new DataObjectSet();
|
||||
foreach($this->sourceItems as $pageIndex=>$item) {
|
||||
$output->push(Object::create($this->itemClass,$item, $this, $pageStart+$pageIndex));
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the popup-title by javascript. Make sure to use FormResponse in ajax-requests,
|
||||
* otherwise the title-change will only take effect on items existing during page-load.
|
||||
*
|
||||
*
|
||||
* @param $caption String
|
||||
*/
|
||||
function setPopupCaption($caption) {
|
||||
$this->popupCaption = Convert::raw2js($caption);
|
||||
$this->popupCaption = Convert::raw2js($caption);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Renders view, edit and add, depending on the given information.
|
||||
* The form needs several parameters to function independently of its "parent-form", some derived from the context into a hidden-field,
|
||||
@ -209,7 +209,7 @@ JS;
|
||||
* CAUTION: "ID" in the DetailForm would be the "childID" in the overview table.
|
||||
*/
|
||||
function DetailForm() {
|
||||
|
||||
|
||||
// Get all the requests
|
||||
$ID = isset($_REQUEST['ctf']['ID']) ? Convert::raw2xml($_REQUEST['ctf']['ID']) : null;
|
||||
$childID = isset($_REQUEST['ctf']['childID']) ? Convert::raw2xml($_REQUEST['ctf']['childID']) : null;
|
||||
@ -265,11 +265,11 @@ JS;
|
||||
|
||||
// the ID field confuses the Controller-logic in finding the right view for ReferencedField
|
||||
$detailFields->removeByName('ID');
|
||||
|
||||
|
||||
// add a namespaced ID instead thats "converted" by saveComplexTableField()
|
||||
$detailFields->push(new HiddenField("ctf[childID]","",$childID));
|
||||
$detailFields->push(new HiddenField("ctf[ClassName]","",$this->sourceClass));
|
||||
|
||||
|
||||
$readonly = ($this->methodName == "show");
|
||||
|
||||
// if no custom validator is set, and there's on present on the object (e.g. Member), use it
|
||||
@ -281,7 +281,7 @@ JS;
|
||||
|
||||
if (is_numeric($childID)) {
|
||||
if ($this->methodName == "show" || $this->methodName == "edit") {
|
||||
|
||||
|
||||
$form->loadDataFrom($childData);
|
||||
}
|
||||
}
|
||||
@ -289,10 +289,10 @@ JS;
|
||||
if ($this->methodName == "show") {
|
||||
$form->makeReadonly();
|
||||
}
|
||||
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $validator Validator
|
||||
*/
|
||||
@ -303,87 +303,87 @@ JS;
|
||||
/**
|
||||
* Returns the content of this formfield without surrounding layout. Triggered by Javascript
|
||||
* to update content after a DetailForm-save-action.
|
||||
*
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
function ajax_render() {
|
||||
return $this->renderWith($this->template);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Just a hook, processed in {DetailForm()}
|
||||
*
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
function show() {
|
||||
if($this->Can('show') !== true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$this->methodName = "edit";
|
||||
|
||||
|
||||
$this->sourceItems = $this->sourceItems();
|
||||
|
||||
|
||||
$this->pageSize = 1;
|
||||
|
||||
if(isset($_REQUEST['ctf'][$this->Name()]['start']) && is_numeric($_REQUEST['ctf'][$this->Name()]['start'])) {
|
||||
$this->unpagedSourceItems->setPageLimits($_REQUEST['ctf'][$this->Name()]['start'], $this->pageSize, $this->totalCount);
|
||||
}
|
||||
|
||||
|
||||
echo $this->renderWith($this->templatePopup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Just a hook, processed in {DetailForm()}
|
||||
*
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
function edit() {
|
||||
if($this->Can('edit') !== true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$this->methodName = "edit";
|
||||
|
||||
|
||||
$this->sourceItems = $this->sourceItems();
|
||||
|
||||
|
||||
$this->pageSize = 1;
|
||||
|
||||
|
||||
if(is_numeric($_REQUEST['ctf']['start'])) {
|
||||
$this->unpagedSourceItems->setPageLimits($_REQUEST['ctf']['start'], $this->pageSize, $this->totalCount);
|
||||
}
|
||||
|
||||
|
||||
echo $this->renderWith($this->templatePopup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Just a hook, processed in {DetailForm()}
|
||||
*
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
function add() {
|
||||
if($this->Can('add') !== true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$this->methodName = "add";
|
||||
|
||||
|
||||
echo $this->renderWith($this->templatePopup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the number of columns needed for colspans
|
||||
* used in template
|
||||
*
|
||||
*
|
||||
* @return Int
|
||||
*/
|
||||
function ItemCount() {
|
||||
return count($this->fieldList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used to toggle paging (makes no sense when adding a record)
|
||||
*
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
function IsAddMode() {
|
||||
@ -411,7 +411,7 @@ JS;
|
||||
function PopupBaseLink() {
|
||||
return $this->FormAction() . "&action_callfieldmethod&fieldName={$this->Name()}&ctf[ID]={$this->sourceID()}";
|
||||
}
|
||||
|
||||
|
||||
function PopupCurrentItem() {
|
||||
return $_REQUEST['ctf']['start']+1;
|
||||
}
|
||||
@ -420,27 +420,27 @@ JS;
|
||||
if(!is_numeric($_REQUEST['ctf']['start']) || $_REQUEST['ctf']['start'] == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
$item = $this->unpagedSourceItems->First();
|
||||
$start = 0;
|
||||
return $this->PopupBaseLink() . "&methodName={$_REQUEST['methodName']}&ctf[childID]={$item->ID}&ctf[start]={$start}";
|
||||
}
|
||||
|
||||
|
||||
function PopupLastLink() {
|
||||
if(!is_numeric($_REQUEST['ctf']['start']) || $_REQUEST['ctf']['start'] == $this->totalCount-1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
$item = $this->unpagedSourceItems->Last();
|
||||
$start = $this->totalCount - 1;
|
||||
return $this->PopupBaseLink() . "&methodName={$_REQUEST['methodName']}&ctf[childID]={$item->ID}&ctf[start]={$start}";
|
||||
}
|
||||
|
||||
|
||||
function PopupNextLink() {
|
||||
if(!is_numeric($_REQUEST['ctf']['start']) || $_REQUEST['ctf']['start'] == $this->totalCount-1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
$item = $this->unpagedSourceItems->getOffset($_REQUEST['ctf']['start'] + 1);
|
||||
|
||||
$start = $_REQUEST['ctf']['start'] + 1;
|
||||
@ -451,7 +451,7 @@ JS;
|
||||
if(!is_numeric($_REQUEST['ctf']['start']) || $_REQUEST['ctf']['start'] == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
$item = $this->unpagedSourceItems->getOffset($_REQUEST['ctf']['start'] - 1);
|
||||
|
||||
$start = $_REQUEST['ctf']['start'] - 1;
|
||||
@ -487,8 +487,8 @@ JS;
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* #################################
|
||||
* Utilty
|
||||
@ -500,7 +500,7 @@ JS;
|
||||
*/
|
||||
function PopupClasses() {
|
||||
global $_ALL_CLASSES;
|
||||
|
||||
|
||||
$items = array();
|
||||
$parents = $_ALL_CLASSES['parents'][$this->class];
|
||||
foreach($parents as $parent) {
|
||||
@ -510,11 +510,11 @@ JS;
|
||||
|
||||
return implode(" ", $items);
|
||||
}
|
||||
|
||||
|
||||
function AddLink() {
|
||||
return "{$this->PopupBaseLink()}&methodName=add";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return FieldSet
|
||||
*/
|
||||
@ -525,11 +525,11 @@ JS;
|
||||
}
|
||||
return $fieldset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines on which relation-class the DetailForm is saved
|
||||
* by looking at the surrounding form-record.
|
||||
*
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
function getParentClass() {
|
||||
@ -547,13 +547,13 @@ JS;
|
||||
* (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.
|
||||
*/
|
||||
@ -575,12 +575,12 @@ JS;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function setTemplatePopup($template) {
|
||||
$this->templatePopup = $template;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
class ComplexTableField_Item extends TableListField_Item {
|
||||
@ -588,13 +588,13 @@ class ComplexTableField_Item extends TableListField_Item {
|
||||
* Needed to transfer pagination-status from overview.
|
||||
*/
|
||||
protected $start;
|
||||
|
||||
|
||||
function __construct(DataObject $item, ComplexTableField $parent, $start) {
|
||||
$this->start = $start;
|
||||
|
||||
|
||||
parent::__construct($item, $parent);
|
||||
}
|
||||
|
||||
|
||||
function PopupBaseLink() {
|
||||
return $this->parent->FormAction() . "&action_callfieldmethod&fieldName={$this->parent->Name()}&ctf[childID]={$this->item->ID}&ctf[ID]={$this->parent->sourceID()}&ctf[start]={$this->start}";
|
||||
}
|
||||
@ -615,7 +615,7 @@ class ComplexTableField_Item extends TableListField_Item {
|
||||
|
||||
/**
|
||||
* ComplexTablefield_popup is rendered with a lightbox and can load a more
|
||||
* detailed view of the source class your presenting.
|
||||
* detailed view of the source class your presenting.
|
||||
* You can customise the fields and requirements as well as any
|
||||
* permissions you might need.
|
||||
*/
|
||||
@ -623,10 +623,10 @@ class ComplexTableField_Popup extends Form {
|
||||
protected $sourceClass;
|
||||
|
||||
function __construct($controller, $name, $field, $sourceClass, $readonly=false, $validator = null) {
|
||||
|
||||
|
||||
/**
|
||||
* WARNING: DO NOT CHANGE THE ORDER OF THESE JS FILES
|
||||
* Some have special requirements.
|
||||
* Some have special requirements.
|
||||
*/
|
||||
Requirements::clear();
|
||||
//Requirements::css('cms/css/layout.css');
|
||||
@ -647,7 +647,7 @@ class ComplexTableField_Popup extends Form {
|
||||
Requirements::javascript("sapphire/javascript/TableField.js");
|
||||
Requirements::javascript("sapphire/javascript/ComplexTableField.js");
|
||||
Requirements::javascript("sapphire/javascript/ComplexTableField_popup.js");
|
||||
|
||||
|
||||
$this->sourceClass = $sourceClass;
|
||||
if(singleton($sourceClass)->hasMethod('getRequirementsForPopup')){
|
||||
singleton($sourceClass)->getRequirementsForPopup();
|
||||
@ -667,23 +667,23 @@ class ComplexTableField_Popup extends Form {
|
||||
function FieldHolder() {
|
||||
return $this->renderWith('ComplexTableField_Form');
|
||||
}
|
||||
|
||||
|
||||
function ShowPagination() {
|
||||
return $this->controller->ShowPagination();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Use the URL-Parameter "action_saveComplexTableField"
|
||||
* to provide a clue to the main controller if the main form has to be rendered,
|
||||
* even if there is no action relevant for the main controller (to provide the instance of ComplexTableField
|
||||
* which in turn saves the record.
|
||||
*
|
||||
* which in turn saves the record.
|
||||
*
|
||||
* @see {Form::ReferencedField}).
|
||||
*/
|
||||
function saveComplexTableField() {
|
||||
$id = Convert::raw2sql($_REQUEST['ctf']['childID']);
|
||||
|
||||
|
||||
if (is_numeric($id)) {
|
||||
$childObject = DataObject::get_by_id($this->sourceClass, $id);
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user