コード例 #1
0
 public function __construct($name, $title = null, $value = '', $extension = null, $areaCode = null, $countryCode = null)
 {
     $this->areaCode = $areaCode;
     $this->ext = $extension;
     $this->countryCode = $countryCode;
     // Build fields
     $fields = new FieldList();
     if ($this->countryCode !== null) {
         $countryField = NumericField::create($name . '[Country]', false, $countryCode, 4)->addExtraClass('phonenumber-field__country');
         $fields->push($countryField);
     }
     if ($this->areaCode !== null) {
         $areaField = NumericField::create($name . '[Area]', false, $areaCode, 4)->addExtraClass('phonenumber-field__area');
         $fields->push($areaField);
     }
     $numberField = NumericField::create($name . '[Number]', false, null, 10)->addExtraClass('phonenumber-field__number');
     $fields->push($numberField);
     if ($this->ext !== null) {
         $extensionField = NumericField::create($name . '[Extension]', false, $extension, 6)->addExtraClass('phonenumber-field__extension');
         $fields->push($extensionField);
     }
     parent::__construct($title, $fields);
     $this->setName($name);
     if (isset($value)) {
         $this->setValue($value);
     }
 }
コード例 #2
0
 /**
  * Constructor
  *
  * @param Controller $controller The parent controller, necessary to create the appropriate form action tag.
  * @param string $name The method on the controller that will return this form object.
  * @param FieldList|FormField $fields All of the fields in the form - a {@link FieldList} of
  * {@link FormField} objects.
  * @param FieldList|FormAction $actions All of the action buttons in the form - a {@link FieldList} of
  */
 public function __construct($controller, $name, $fields = null, $actions = null)
 {
     if (isset($_REQUEST['BackURL'])) {
         $backURL = $_REQUEST['BackURL'];
     } else {
         $backURL = Session::get('BackURL');
     }
     if (!$fields) {
         $fields = new FieldList();
         // Security/changepassword?h=XXX redirects to Security/changepassword
         // without GET parameter to avoid potential HTTP referer leakage.
         // In this case, a user is not logged in, and no 'old password' should be necessary.
         if (Member::currentUser()) {
             $fields->push(new PasswordField("OldPassword", _t('Member.YOUROLDPASSWORD', "Your old password")));
         }
         $fields->push(new PasswordField("NewPassword1", _t('Member.NEWPASSWORD', "New Password")));
         $fields->push(new PasswordField("NewPassword2", _t('Member.CONFIRMNEWPASSWORD', "Confirm New Password")));
     }
     if (!$actions) {
         $actions = new FieldList(new FormAction("doChangePassword", _t('Member.BUTTONCHANGEPASSWORD', "Change Password")));
     }
     if (isset($backURL)) {
         $fields->push(new HiddenField('BackURL', 'BackURL', $backURL));
     }
     parent::__construct($controller, $name, $fields, $actions);
 }
コード例 #3
0
 /**
  * Return the form's fields - used by the templates
  *
  * @return FieldList The form fields
  */
 public function Fields()
 {
     foreach ($this->getExtraFields() as $field) {
         if (!$this->fields->fieldByName($field->getName())) {
             $this->fields->push($field);
         }
     }
     return $this->fields;
 }
コード例 #4
0
 public function __construct(Controller $controller, $name)
 {
     // Set default fields
     $fields = new FieldList(HiddenField::create("AuthenticationMethod", null, $this->authenticator_class, $this), HiddenField::create('tempid', null, $controller->getRequest()->requestVar('tempid')), PasswordField::create("Password", _t('Member.PASSWORD', 'Password')), LiteralField::create('forgotPassword', sprintf('<p id="ForgotPassword"><a href="%s" target="_top">%s</a></p>', $this->getExternalLink('lostpassword'), _t('CMSMemberLoginForm.BUTTONFORGOTPASSWORD', "Forgot password?"))));
     if (Security::config()->autologin_enabled) {
         $fields->push(CheckboxField::create("Remember", _t('Member.REMEMBERME', "Remember me next time?")));
     }
     // Determine returnurl to redirect to parent page
     $logoutLink = $this->getExternalLink('logout');
     if ($returnURL = $controller->getRequest()->requestVar('BackURL')) {
         $logoutLink = Controller::join_links($logoutLink, '?BackURL=' . urlencode($returnURL));
     }
     // Make actions
     $actions = new FieldList(FormAction::create('dologin', _t('CMSMemberLoginForm.BUTTONLOGIN', "Log back in")), LiteralField::create('doLogout', sprintf('<p id="doLogout"><a href="%s" target="_top">%s</a></p>', $logoutLink, _t('CMSMemberLoginForm.BUTTONLOGOUT', "Log out"))));
     parent::__construct($controller, $name, $fields, $actions);
 }
コード例 #5
0
 /**
  * @param string $name
  * @param string $title
  * @param mixed $value
  * @param Form $form
  * @param boolean $showOnClick
  * @param string $titleConfirmField Alternate title (not localizeable)
  */
 public function __construct($name, $title = null, $value = "", $form = null, $showOnClick = false, $titleConfirmField = null)
 {
     // Set field title
     $title = isset($title) ? $title : _t('Member.PASSWORD', 'Password');
     // naming with underscores to prevent values from actually being saved somewhere
     $this->children = new FieldList($this->passwordField = new PasswordField("{$name}[_Password]", $title), $this->confirmPasswordfield = new PasswordField("{$name}[_ConfirmPassword]", isset($titleConfirmField) ? $titleConfirmField : _t('Member.CONFIRMPASSWORD', 'Confirm Password')));
     // has to be called in constructor because Field() isn't triggered upon saving the instance
     if ($showOnClick) {
         $this->children->push($this->hiddenField = new HiddenField("{$name}[_PasswordFieldVisible]"));
     }
     // disable auto complete
     foreach ($this->children as $child) {
         /** @var FormField $child */
         $child->setAttribute('autocomplete', 'off');
     }
     $this->showOnClick = $showOnClick;
     parent::__construct($name, $title);
     $this->setValue($value);
 }
コード例 #6
0
 /**
  * Generate a CSV import form for a single {@link DataObject} subclass.
  *
  * @return Form|false
  */
 public function ImportForm()
 {
     $modelSNG = singleton($this->modelClass);
     $modelName = $modelSNG->i18n_singular_name();
     // check if a import form should be generated
     if (!$this->showImportForm || is_array($this->showImportForm) && !in_array($this->modelClass, $this->showImportForm)) {
         return false;
     }
     $importers = $this->getModelImporters();
     if (!$importers || !isset($importers[$this->modelClass])) {
         return false;
     }
     if (!$modelSNG->canCreate(Member::currentUser())) {
         return false;
     }
     $fields = new FieldList(new HiddenField('ClassName', _t('ModelAdmin.CLASSTYPE'), $this->modelClass), new FileField('_CsvFile', false));
     // get HTML specification for each import (column names etc.)
     $importerClass = $importers[$this->modelClass];
     /** @var BulkLoader $importer */
     $importer = new $importerClass($this->modelClass);
     $spec = $importer->getImportSpec();
     $specFields = new ArrayList();
     foreach ($spec['fields'] as $name => $desc) {
         $specFields->push(new ArrayData(array('Name' => $name, 'Description' => $desc)));
     }
     $specRelations = new ArrayList();
     foreach ($spec['relations'] as $name => $desc) {
         $specRelations->push(new ArrayData(array('Name' => $name, 'Description' => $desc)));
     }
     $specHTML = $this->customise(array('ClassName' => $this->sanitiseClassName($this->modelClass), 'ModelName' => Convert::raw2att($modelName), 'Fields' => $specFields, 'Relations' => $specRelations))->renderWith($this->getTemplatesWithSuffix('_ImportSpec'));
     $fields->push(new LiteralField("SpecFor{$modelName}", $specHTML));
     $fields->push(new CheckboxField('EmptyBeforeImport', _t('ModelAdmin.EMPTYBEFOREIMPORT', 'Replace data'), false));
     $actions = new FieldList(new FormAction('import', _t('ModelAdmin.IMPORT', 'Import from CSV')));
     $form = new Form($this, "ImportForm", $fields, $actions);
     $form->setFormAction(Controller::join_links($this->Link($this->sanitiseClassName($this->modelClass)), 'ImportForm'));
     $this->extend('updateImportForm', $form);
     return $form;
 }
コード例 #7
0
 /**
  * Return a disabled version of this field. Keeps the composition but returns disabled
  * versions of all the child {@link FormField} objects.
  *
  * @return CompositeField
  */
 public function performDisabledTransformation()
 {
     $newChildren = new FieldList();
     $clone = clone $this;
     if ($clone->getChildren()) {
         foreach ($clone->getChildren() as $child) {
             /** @var FormField $child */
             $child = $child->transform(new DisabledTransformation());
             $newChildren->push($child);
         }
     }
     $clone->setChildren($newChildren);
     $clone->setDisabled(true);
     $clone->addExtraClass($this->extraClass());
     $clone->setDescription($this->getDescription());
     foreach ($this->attributes as $k => $v) {
         $clone->setAttribute($k, $v);
     }
     return $clone;
 }
 /**
  * Build the set of form field actions for this DataObject
  *
  * @return FieldList
  */
 protected function getFormActions()
 {
     $canEdit = $this->record->canEdit();
     $canDelete = $this->record->canDelete();
     $actions = new FieldList();
     if ($this->record->ID !== 0) {
         if ($canEdit) {
             $actions->push(FormAction::create('doSave', _t('GridFieldDetailForm.Save', 'Save'))->setUseButtonTag(true)->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept'));
         }
         if ($canDelete) {
             $actions->push(FormAction::create('doDelete', _t('GridFieldDetailForm.Delete', 'Delete'))->setUseButtonTag(true)->addExtraClass('ss-ui-action-destructive action-delete'));
         }
     } else {
         // adding new record
         //Change the Save label to 'Create'
         $actions->push(FormAction::create('doSave', _t('GridFieldDetailForm.Create', 'Create'))->setUseButtonTag(true)->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'add'));
         // Add a Cancel link which is a button-like link and link back to one level up.
         $crumbs = $this->Breadcrumbs();
         if ($crumbs && $crumbs->count() >= 2) {
             $oneLevelUp = $crumbs->offsetGet($crumbs->count() - 2);
             $text = sprintf("<a class=\"%s\" href=\"%s\">%s</a>", "crumb ss-ui-button ss-ui-action-destructive cms-panel-link ui-corner-all", $oneLevelUp->Link, _t('GridFieldDetailForm.CancelBtn', 'Cancel'));
             $actions->push(new LiteralField('cancelbutton', $text));
         }
     }
     $this->extend('updateFormActions', $actions);
     return $actions;
 }
コード例 #9
0
 protected function getFormFields(Controller $controller, $name, $context = [])
 {
     $record = $context['Record'];
     // Build standard fields for all folders / files
     /** @var File $record */
     $fields = new FieldList(HeaderField::create('TitleHeader', $record ? $record->Title : null, 1)->addExtraClass('editor__heading'), LiteralField::create("IconFull", $this->getIconMarkup($record))->addExtraClass('editor__file-preview'), $this->getFormFieldTabs($record, $context));
     if ($record) {
         $fields->push(HiddenField::create('ID', $record->ID));
     }
     $this->invokeWithExtensions('updateFormFields', $fields, $controller, $name, $context);
     return $fields;
 }
コード例 #10
0
 /**
  * Transform this FieldList with a given tranform method,
  * e.g. $this->transform(new ReadonlyTransformation())
  *
  * @param FormTransformation $trans
  * @return FieldList
  */
 public function transform($trans)
 {
     $this->flushFieldsCache();
     $newFields = new FieldList();
     foreach ($this as $field) {
         $newFields->push($field->transform($trans));
     }
     return $newFields;
 }
コード例 #11
0
 /**
  * Note: Doesn't call {@link FormField->setForm()}
  * on the returned {@link HiddenField}, you'll need to take
  * care of this yourself.
  *
  * @param FieldList $fieldset
  * @return HiddenField|false
  */
 public function updateFieldSet(&$fieldset)
 {
     if (!$fieldset->fieldByName($this->getName())) {
         $field = new HiddenField($this->getName(), null, $this->getValue());
         $fieldset->push($field);
         return $field;
     } else {
         return false;
     }
 }
コード例 #12
0
 /**
  * Adds additional form actions
  *
  * @param FieldList $actions
  * @param Controller $controller
  * @param string $name
  * @param array $context
  */
 public function updateFormActions(FieldList &$actions, Controller $controller, $name, $context = [])
 {
     // Add publish button if record is versioned
     if (empty($context['Record'])) {
         return;
     }
     $record = $context['Record'];
     if ($record->hasExtension(Versioned::class)) {
         $actions->push(new FormAction('publish', 'Publish'));
     }
 }
コード例 #13
0
 /**
  * Get list of fields for previewing this records details
  *
  * @return FieldList
  */
 protected function getDetailFields()
 {
     $fields = new FieldList(ReadonlyField::create("FileType", _t('AssetTableField.TYPE', 'File type'), $this->getFileType()), HTMLReadonlyField::create('ClickableURL', _t('AssetTableField.URL', 'URL'), $this->getExternalLink()));
     // Get file size
     if ($this->getSize()) {
         $fields->insertAfter('FileType', ReadonlyField::create("Size", _t('AssetTableField.SIZE', 'File size'), $this->getSize()));
     }
     // Get modified details of local record
     if ($this->getFile()) {
         $fields->push(new DateField_Disabled("Created", _t('AssetTableField.CREATED', 'First uploaded'), $this->getFile()->Created));
         $fields->push(new DateField_Disabled("LastEdited", _t('AssetTableField.LASTEDIT', 'Last changed'), $this->getFile()->LastEdited));
     }
     return $fields;
 }
コード例 #14
0
 /**
  * Caution: Only call on instances, not through a singleton.
  * The "root group" fields will be created through {@link SecurityAdmin->EditForm()}.
  *
  * @return FieldList
  */
 public function getCMSFields()
 {
     $fields = new FieldList(new TabSet("Root", new Tab('Members', _t('SecurityAdmin.MEMBERS', 'Members'), new TextField("Title", $this->fieldLabel('Title')), $parentidfield = DropdownField::create('ParentID', $this->fieldLabel('Parent'), Group::get()->exclude('ID', $this->ID)->map('ID', 'Breadcrumbs'))->setEmptyString(' '), new TextareaField('Description', $this->fieldLabel('Description'))), $permissionsTab = new Tab('Permissions', _t('SecurityAdmin.PERMISSIONS', 'Permissions'), $permissionsField = new PermissionCheckboxSetField('Permissions', false, 'SilverStripe\\Security\\Permission', 'GroupID', $this))));
     $parentidfield->setDescription(_t('Group.GroupReminder', 'If you choose a parent group, this group will take all it\'s roles'));
     // Filter permissions
     // TODO SecurityAdmin coupling, not easy to get to the form fields through GridFieldDetailForm
     $permissionsField->setHiddenPermissions((array) Config::inst()->get('SilverStripe\\Admin\\SecurityAdmin', 'hidden_permissions'));
     if ($this->ID) {
         $group = $this;
         $config = GridFieldConfig_RelationEditor::create();
         $config->addComponent(new GridFieldButtonRow('after'));
         $config->addComponents(new GridFieldExportButton('buttons-after-left'));
         $config->addComponents(new GridFieldPrintButton('buttons-after-left'));
         /** @var GridFieldAddExistingAutocompleter $autocompleter */
         $autocompleter = $config->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldAddExistingAutocompleter');
         /** @skipUpgrade */
         $autocompleter->setResultsFormat('$Title ($Email)')->setSearchFields(array('FirstName', 'Surname', 'Email'));
         /** @var GridFieldDetailForm $detailForm */
         $detailForm = $config->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldDetailForm');
         $detailForm->setValidator(Member_Validator::create())->setItemEditFormCallback(function ($form, $component) use($group) {
             /** @var Form $form */
             $record = $form->getRecord();
             $groupsField = $form->Fields()->dataFieldByName('DirectGroups');
             if ($groupsField) {
                 // If new records are created in a group context,
                 // set this group by default.
                 if ($record && !$record->ID) {
                     $groupsField->setValue($group->ID);
                 } elseif ($record && $record->ID) {
                     // TODO Mark disabled once chosen.js supports it
                     // $groupsField->setDisabledItems(array($group->ID));
                     $form->Fields()->replaceField('DirectGroups', $groupsField->performReadonlyTransformation());
                 }
             }
         });
         $memberList = GridField::create('Members', false, $this->DirectMembers(), $config)->addExtraClass('members_grid');
         // @todo Implement permission checking on GridField
         //$memberList->setPermissions(array('edit', 'delete', 'export', 'add', 'inlineadd'));
         $fields->addFieldToTab('Root.Members', $memberList);
     }
     // Only add a dropdown for HTML editor configurations if more than one is available.
     // Otherwise Member->getHtmlEditorConfigForCMS() will default to the 'cms' configuration.
     $editorConfigMap = HTMLEditorConfig::get_available_configs_map();
     if (count($editorConfigMap) > 1) {
         $fields->addFieldToTab('Root.Permissions', new DropdownField('HtmlEditorConfig', 'HTML Editor Configuration', $editorConfigMap), 'Permissions');
     }
     if (!Permission::check('EDIT_PERMISSIONS')) {
         $fields->removeFieldFromTab('Root', 'Permissions');
     }
     // Only show the "Roles" tab if permissions are granted to edit them,
     // and at least one role exists
     if (Permission::check('APPLY_ROLES') && DataObject::get('SilverStripe\\Security\\PermissionRole')) {
         $fields->findOrMakeTab('Root.Roles', _t('SecurityAdmin.ROLES', 'Roles'));
         $fields->addFieldToTab('Root.Roles', new LiteralField("", "<p>" . _t('SecurityAdmin.ROLESDESCRIPTION', "Roles are predefined sets of permissions, and can be assigned to groups.<br />" . "They are inherited from parent groups if required.") . '<br />' . sprintf('<a href="%s" class="add-role">%s</a>', SecurityAdmin::singleton()->Link('show/root#Root_Roles'), _t('Group.RolesAddEditLink', 'Manage roles')) . "</p>"));
         // Add roles (and disable all checkboxes for inherited roles)
         $allRoles = PermissionRole::get();
         if (!Permission::check('ADMIN')) {
             $allRoles = $allRoles->filter("OnlyAdminCanApply", 0);
         }
         if ($this->ID) {
             $groupRoles = $this->Roles();
             $inheritedRoles = new ArrayList();
             $ancestors = $this->getAncestors();
             foreach ($ancestors as $ancestor) {
                 $ancestorRoles = $ancestor->Roles();
                 if ($ancestorRoles) {
                     $inheritedRoles->merge($ancestorRoles);
                 }
             }
             $groupRoleIDs = $groupRoles->column('ID') + $inheritedRoles->column('ID');
             $inheritedRoleIDs = $inheritedRoles->column('ID');
         } else {
             $groupRoleIDs = array();
             $inheritedRoleIDs = array();
         }
         $rolesField = ListboxField::create('Roles', false, $allRoles->map()->toArray())->setDefaultItems($groupRoleIDs)->setAttribute('data-placeholder', _t('Group.AddRole', 'Add a role for this group'))->setDisabledItems($inheritedRoleIDs);
         if (!$allRoles->count()) {
             $rolesField->setAttribute('data-placeholder', _t('Group.NoRoles', 'No roles found'));
         }
         $fields->addFieldToTab('Root.Roles', $rolesField);
     }
     $fields->push($idField = new HiddenField("ID"));
     $this->extend('updateCMSFields', $fields);
     return $fields;
 }
コード例 #15
0
 /**
  * Determine which properties on the DataObject are
  * searchable, and map them to their default {@link FormField}
  * representations. Used for scaffolding a searchform for {@link ModelAdmin}.
  *
  * Some additional logic is included for switching field labels, based on
  * how generic or specific the field type is.
  *
  * Used by {@link SearchContext}.
  *
  * @param array $_params
  *   'fieldClasses': Associative array of field names as keys and FormField classes as values
  *   'restrictFields': Numeric array of a field name whitelist
  * @return FieldList
  */
 public function scaffoldSearchFields($_params = null)
 {
     $params = array_merge(array('fieldClasses' => false, 'restrictFields' => false), (array) $_params);
     $fields = new FieldList();
     foreach ($this->searchableFields() as $fieldName => $spec) {
         if ($params['restrictFields'] && !in_array($fieldName, $params['restrictFields'])) {
             continue;
         }
         // If a custom fieldclass is provided as a string, use it
         $field = null;
         if ($params['fieldClasses'] && isset($params['fieldClasses'][$fieldName])) {
             $fieldClass = $params['fieldClasses'][$fieldName];
             $field = new $fieldClass($fieldName);
             // If we explicitly set a field, then construct that
         } else {
             if (isset($spec['field'])) {
                 // If it's a string, use it as a class name and construct
                 if (is_string($spec['field'])) {
                     $fieldClass = $spec['field'];
                     $field = new $fieldClass($fieldName);
                     // If it's a FormField object, then just use that object directly.
                 } else {
                     if ($spec['field'] instanceof FormField) {
                         $field = $spec['field'];
                         // Otherwise we have a bug
                     } else {
                         user_error("Bad value for searchable_fields, 'field' value: " . var_export($spec['field'], true), E_USER_WARNING);
                     }
                 }
                 // Otherwise, use the database field's scaffolder
             } else {
                 $field = $this->relObject($fieldName)->scaffoldSearchField();
             }
         }
         // Allow fields to opt out of search
         if (!$field) {
             continue;
         }
         if (strstr($fieldName, '.')) {
             $field->setName(str_replace('.', '__', $fieldName));
         }
         $field->setTitle($spec['title']);
         $fields->push($field);
     }
     return $fields;
 }
コード例 #16
0
 /**
  * Adds a new {@link FormField} instance.
  *
  * @param FormField $field
  */
 public function addField($field)
 {
     $this->fields->push($field);
 }
コード例 #17
0
 /**
  * FieldList::changeFieldOrder() should place specified fields in given
  * order then add any unspecified remainders at the end. Can be given an
  * array or list of arguments.
  */
 public function testChangeFieldOrder()
 {
     $fieldNames = array('A', 'B', 'C', 'D', 'E');
     $setArray = new FieldList();
     $setArgs = new FieldList();
     foreach ($fieldNames as $fN) {
         $setArray->push(new TextField($fN));
         $setArgs->push(new TextField($fN));
     }
     $setArray->changeFieldOrder(array('D', 'B', 'E'));
     $this->assertEquals(0, $setArray->fieldPosition('D'));
     $this->assertEquals(1, $setArray->fieldPosition('B'));
     $this->assertEquals(2, $setArray->fieldPosition('E'));
     $this->assertEquals(3, $setArray->fieldPosition('A'));
     $this->assertEquals(4, $setArray->fieldPosition('C'));
     $setArgs->changeFieldOrder('D', 'B', 'E');
     $this->assertEquals(0, $setArgs->fieldPosition('D'));
     $this->assertEquals(1, $setArgs->fieldPosition('B'));
     $this->assertEquals(2, $setArgs->fieldPosition('E'));
     $this->assertEquals(3, $setArgs->fieldPosition('A'));
     $this->assertEquals(4, $setArgs->fieldPosition('C'));
     unset($setArray, $setArgs);
 }
コード例 #18
0
 /**
  * Gets the form fields as defined through the metadata
  * on {@link $obj} and the custom parameters passed to FormScaffolder.
  * Depending on those parameters, the fields can be used in ajax-context,
  * contain {@link TabSet}s etc.
  *
  * @return FieldList
  */
 public function getFieldList()
 {
     $fields = new FieldList();
     // tabbed or untabbed
     if ($this->tabbed) {
         $fields->push(new TabSet("Root", $mainTab = new Tab("Main")));
         $mainTab->setTitle(_t('SiteTree.TABMAIN', "Main"));
     }
     // Add logical fields directly specified in db config
     foreach ($this->obj->config()->db as $fieldName => $fieldType) {
         // Skip restricted fields
         if ($this->restrictFields && !in_array($fieldName, $this->restrictFields)) {
             continue;
         }
         // @todo Pass localized title
         if ($this->fieldClasses && isset($this->fieldClasses[$fieldName])) {
             $fieldClass = $this->fieldClasses[$fieldName];
             $fieldObject = new $fieldClass($fieldName);
         } else {
             $fieldObject = $this->obj->dbObject($fieldName)->scaffoldFormField(null, $this->getParamsArray());
         }
         // Allow fields to opt-out of scaffolding
         if (!$fieldObject) {
             continue;
         }
         $fieldObject->setTitle($this->obj->fieldLabel($fieldName));
         if ($this->tabbed) {
             $fields->addFieldToTab("Root.Main", $fieldObject);
         } else {
             $fields->push($fieldObject);
         }
     }
     // add has_one relation fields
     if ($this->obj->hasOne()) {
         foreach ($this->obj->hasOne() as $relationship => $component) {
             if ($this->restrictFields && !in_array($relationship, $this->restrictFields)) {
                 continue;
             }
             $fieldName = $component === 'SilverStripe\\ORM\\DataObject' ? $relationship : "{$relationship}ID";
             if ($this->fieldClasses && isset($this->fieldClasses[$fieldName])) {
                 $fieldClass = $this->fieldClasses[$fieldName];
                 $hasOneField = new $fieldClass($fieldName);
             } else {
                 $hasOneField = $this->obj->dbObject($fieldName)->scaffoldFormField(null, $this->getParamsArray());
             }
             if (empty($hasOneField)) {
                 continue;
             }
             // Allow fields to opt out of scaffolding
             $hasOneField->setTitle($this->obj->fieldLabel($relationship));
             if ($this->tabbed) {
                 $fields->addFieldToTab("Root.Main", $hasOneField);
             } else {
                 $fields->push($hasOneField);
             }
         }
     }
     // only add relational fields if an ID is present
     if ($this->obj->ID) {
         // add has_many relation fields
         if ($this->obj->hasMany() && ($this->includeRelations === true || isset($this->includeRelations['has_many']))) {
             foreach ($this->obj->hasMany() as $relationship => $component) {
                 if ($this->tabbed) {
                     $fields->findOrMakeTab("Root.{$relationship}", $this->obj->fieldLabel($relationship));
                 }
                 $fieldClass = isset($this->fieldClasses[$relationship]) ? $this->fieldClasses[$relationship] : 'SilverStripe\\Forms\\GridField\\GridField';
                 /** @var GridField $grid */
                 $grid = Object::create($fieldClass, $relationship, $this->obj->fieldLabel($relationship), $this->obj->{$relationship}(), GridFieldConfig_RelationEditor::create());
                 if ($this->tabbed) {
                     $fields->addFieldToTab("Root.{$relationship}", $grid);
                 } else {
                     $fields->push($grid);
                 }
             }
         }
         if ($this->obj->manyMany() && ($this->includeRelations === true || isset($this->includeRelations['many_many']))) {
             foreach ($this->obj->manyMany() as $relationship => $component) {
                 if ($this->tabbed) {
                     $fields->findOrMakeTab("Root.{$relationship}", $this->obj->fieldLabel($relationship));
                 }
                 $fieldClass = isset($this->fieldClasses[$relationship]) ? $this->fieldClasses[$relationship] : 'SilverStripe\\Forms\\GridField\\GridField';
                 /** @var GridField $grid */
                 $grid = Object::create($fieldClass, $relationship, $this->obj->fieldLabel($relationship), $this->obj->{$relationship}(), GridFieldConfig_RelationEditor::create());
                 if ($this->tabbed) {
                     $fields->addFieldToTab("Root.{$relationship}", $grid);
                 } else {
                     $fields->push($grid);
                 }
             }
         }
     }
     return $fields;
 }