Version: current

      1 <?php
      2 /**
      3  *
      4  * @package sapphire
      5  * @subpackage forms
      6  *
      7  * @uses DBField::scaffoldFormField()
      8  * @uses DataObject::fieldLabels()
      9  */
     10 class FormScaffolder extends Object {
     11
     12     /**
     13      * @var DataObject $obj The object defining the fields to be scaffolded
     14      * through its metadata like $db, $searchable_fields, etc.
     15      */
     16     protected $obj;
     17
     18     /**
     19      * @var boolean $tabbed Return fields in a tabset, with all main fields in the path "Root.Main",
     20      * relation fields in "Root.<relationname>" (if {@link $includeRelations} is enabled).
     21      */
     22     public $tabbed = false;
     23
     24     /**
     25      * @var boolean $ajaxSafe
     26      */
     27     public $ajaxSafe = false;
     28
     29     /**
     30      * @var array $restrictFields Numeric array of a field name whitelist.
     31      * If left blank, all fields from {@link DataObject->db()} will be included.
     32      *
     33      * @todo Implement restrictions for has_many and many_many relations.
     34      */
     35     public $restrictFields;
     36
     37     /**
     38      * @var array $fieldClasses Optional mapping of fieldnames to subclasses of {@link FormField}.
     39      * By default the scaffolder will determine the field instance by {@link DBField::scaffoldFormField()}.
     40      *
     41      * @todo Implement fieldClasses for has_many and many_many relations
     42      */
     43     public $fieldClasses;
     44
     45     /**
     46      * @var boolean $includeRelations Include has_one, has_many and many_many relations
     47      */
     48     public $includeRelations = false;
     49
     50     /**
     51      * @param DataObject $obj
     52      * @param array $params
     53      */
     54     function __construct($obj) {
     55         $this->obj = $obj;
     56         parent::__construct();
     57     }
     58
     59     /**
     60      * Gets the form fields as defined through the metadata
     61      * on {@link $obj} and the custom parameters passed to FormScaffolder.
     62      * Depending on those parameters, the fields can be used in ajax-context,
     63      * contain {@link TabSet}s etc.
     64      *
     65      * @return FieldSet
     66      */
     67     public function getFieldSet() {
     68         $fields = new FieldSet();
     69
     70         // tabbed or untabbed
     71         if($this->tabbed) {
     72             $fields->push(new TabSet("Root", $mainTab = new Tab("Main")));
     73             $mainTab->setTitle(_t('SiteTree.TABMAIN', "Main"));
     74         }
     75
     76         // add database fields
     77         foreach($this->obj->db() as $fieldName => $fieldType) {
     78             if($this->restrictFields && !in_array($fieldName, $this->restrictFields)) continue;
     79
     80             // @todo Pass localized title
     81             if($this->fieldClasses && isset($this->fieldClasses[$fieldName])) {
     82                 $fieldClass = $this->fieldClasses[$fieldName];
     83                 $fieldObject = new $fieldClass($fieldName);
     84             } else {
     85                 $fieldObject = $this->obj->dbObject($fieldName)->scaffoldFormField(null, $this->getParamsArray());
     86             }
     87             $fieldObject->setTitle($this->obj->fieldLabel($fieldName));
     88             if($this->tabbed) {
     89                 $fields->addFieldToTab("Root.Main", $fieldObject);
     90             } else {
     91                 $fields->push($fieldObject);
     92             }
     93         }
     94
     95         // add has_one relation fields
     96         if($this->obj->has_one()) {
     97             foreach($this->obj->has_one() as $relationship => $component) {
     98                 if($this->restrictFields && !in_array($relationship, $this->restrictFields)) continue;
     99                 $hasOneField = $this->obj->dbObject("{$relationship}ID")->scaffoldFormField(null, $this->getParamsArray());
    100                 $hasOneField->setTitle($this->obj->fieldLabel($relationship));
    101                 if($this->tabbed) {
    102                     $fields->addFieldToTab("Root.Main", $hasOneField);
    103                 } else {
    104                     $fields->push($hasOneField);
    105                 }
    106             }
    107         }
    108
    109         // only add relational fields if an ID is present
    110         if($this->obj->ID) {
    111             // add has_many relation fields
    112             if($this->obj->has_many() && ($this->includeRelations === true || isset($this->includeRelations['has_many']))) {
    113                 foreach($this->obj->has_many() as $relationship => $component) {
    114                     if($this->tabbed) {
    115                         $relationTab = $fields->findOrMakeTab(
    116                             "Root.$relationship",
    117                             $this->obj->fieldLabel($relationship)
    118                         );
    119                     }
    120                     $relationshipFields = singleton($component)->summaryFields();
    121                     $foreignKey = $this->obj->getRemoteJoinField($relationship);
    122                     $ctf = new ComplexTableField(
    123                         $this,
    124                         $relationship,
    125                         $component,
    126                         $relationshipFields,
    127                         "getCMSFields",
    128                         "\"$foreignKey\" = " . $this->obj->ID
    129                     );
    130                     $ctf->setPermissions(TableListField::permissions_for_object($component));
    131                     if($this->tabbed) {
    132                         $fields->addFieldToTab("Root.$relationship", $ctf);
    133                     } else {
    134                         $fields->push($ctf);
    135                     }
    136                 }
    137             }
    138
    139             if($this->obj->many_many() && ($this->includeRelations === true || isset($this->includeRelations['many_many']))) {
    140                 foreach($this->obj->many_many() as $relationship => $component) {
    141                     if($this->tabbed) {
    142                         $relationTab = $fields->findOrMakeTab(
    143                             "Root.$relationship",
    144                             $this->obj->fieldLabel($relationship)
    145                         );
    146                     }
    147
    148                     $relationshipFields = singleton($component)->summaryFields();
    149                     $filterWhere = $this->obj->getManyManyFilter($relationship, $component);
    150                     $filterJoin = $this->obj->getManyManyJoin($relationship, $component);
    151                     $ctf =  new ComplexTableField(
    152                         $this,
    153                         $relationship,
    154                         $component,
    155                         $relationshipFields,
    156                         "getCMSFields",
    157                         $filterWhere,
    158                         '',
    159                         $filterJoin
    160                     );
    161                     $ctf->setPermissions(TableListField::permissions_for_object($component));
    162                     $ctf->popupClass = "ScaffoldingComplexTableField_Popup";
    163                     if($this->tabbed) {
    164                         $fields->addFieldToTab("Root.$relationship", $ctf);
    165                     } else {
    166                         $fields->push($ctf);
    167                     }
    168                 }
    169             }
    170         }
    171
    172         return $fields;
    173     }
    174
    175     /**
    176      * Return an array suitable for passing on to {@link DBField->scaffoldFormField()}
    177      * without tying this call to a FormScaffolder interface.
    178      *
    179      * @return array
    180      */
    181     protected function getParamsArray() {
    182         return array(
    183             'tabbed' => $this->tabbed,
    184             'includeRelations' => $this->includeRelations,
    185             'restrictFields' => $this->restrictFields,
    186             'fieldClasses' => $this->fieldClasses,
    187             'ajaxSafe' => $this->ajaxSafe
    188         );
    189     }
    190
    191 }
    192 ?>

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -