public function testTabTitles()
 {
     $set = new FieldList($rootTabSet = new TabSet('Root', $tabSetWithoutTitle = new TabSet('TabSetWithoutTitle'), $tabSetWithTitle = new TabSet('TabSetWithTitle', 'My TabSet Title', new Tab('ExistingChildTab'))));
     $this->assertEquals($tabSetWithTitle->Title(), 'My TabSet Title', 'Automatic conversion of tab identifiers through findOrMakeTab() with FormField::name_to_label()');
     $tabWithoutTitle = $set->findOrMakeTab('Root.TabWithoutTitle');
     $this->assertEquals($tabWithoutTitle->Title(), 'Tab Without Title', 'Automatic conversion of tab identifiers through findOrMakeTab() with FormField::name_to_label()');
     $tabWithTitle = $set->findOrMakeTab('Root.TabWithTitle', 'My Tab with Title');
     $this->assertEquals($tabWithTitle->Title(), 'My Tab with Title', 'Setting of simple tab titles through findOrMakeTab()');
     $childTabWithTitle = $set->findOrMakeTab('Root.TabSetWithoutTitle.NewChildTab', 'My Child Tab Title');
     $this->assertEquals($childTabWithTitle->Title(), 'My Child Tab Title', 'Setting of nested tab titles through findOrMakeTab() works on last child tab');
 }
 /**
  * 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;
 }
 public function getEditForm($id = null, $fields = null)
 {
     // TODO Duplicate record fetching (see parent implementation)
     if (!$id) {
         $id = $this->currentPageID();
     }
     $form = parent::getEditForm($id);
     // TODO Duplicate record fetching (see parent implementation)
     $record = $this->getRecord($id);
     if ($record && !$record->canView()) {
         return Security::permissionFailure($this);
     }
     $memberList = GridField::create('Members', false, Member::get(), $memberListConfig = GridFieldConfig_RecordEditor::create()->addComponent(new GridFieldButtonRow('after'))->addComponent(new GridFieldExportButton('buttons-after-left')))->addExtraClass("members_grid");
     if ($record && method_exists($record, 'getValidator')) {
         $validator = $record->getValidator();
     } else {
         $validator = Member::singleton()->getValidator();
     }
     /** @var GridFieldDetailForm $detailForm */
     $detailForm = $memberListConfig->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldDetailForm');
     $detailForm->setValidator($validator);
     $groupList = GridField::create('Groups', false, Group::get(), GridFieldConfig_RecordEditor::create());
     /** @var GridFieldDataColumns $columns */
     $columns = $groupList->getConfig()->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldDataColumns');
     $columns->setDisplayFields(array('Breadcrumbs' => Group::singleton()->fieldLabel('Title')));
     $columns->setFieldFormatting(array('Breadcrumbs' => function ($val, $item) {
         /** @var Group $item */
         return Convert::raw2xml($item->getBreadcrumbs(' > '));
     }));
     $fields = new FieldList($root = new TabSet('Root', $usersTab = new Tab('Users', _t('SecurityAdmin.Users', 'Users'), new LiteralField('MembersCautionText', sprintf('<div class="alert alert-warning" role="alert">%s</div>', _t('SecurityAdmin.MemberListCaution', 'Caution: Removing members from this list will remove them from all groups and the database'))), $memberList), $groupsTab = new Tab('Groups', singleton('SilverStripe\\Security\\Group')->i18n_plural_name(), $groupList)), new HiddenField('ID', false, 0));
     // Add import capabilities. Limit to admin since the import logic can affect assigned permissions
     if (Permission::check('ADMIN')) {
         $fields->addFieldsToTab('Root.Users', array(new HeaderField('ImportUsersHeader', _t('SecurityAdmin.IMPORTUSERS', 'Import users'), 3), new LiteralField('MemberImportFormIframe', sprintf('<iframe src="%s" id="MemberImportFormIframe" width="100%%" height="330px" frameBorder="0">' . '</iframe>', $this->Link('memberimport')))));
         $fields->addFieldsToTab('Root.Groups', array(new HeaderField('ImportGroupsHeader', _t('SecurityAdmin.IMPORTGROUPS', 'Import groups'), 3), new LiteralField('GroupImportFormIframe', sprintf('<iframe src="%s" id="GroupImportFormIframe" width="100%%" height="330px" frameBorder="0">' . '</iframe>', $this->Link('groupimport')))));
     }
     // Tab nav in CMS is rendered through separate template
     $root->setTemplate('SilverStripe\\Forms\\CMSTabSet');
     // Add roles editing interface
     $rolesTab = null;
     if (Permission::check('APPLY_ROLES')) {
         $rolesField = GridField::create('Roles', false, PermissionRole::get(), GridFieldConfig_RecordEditor::create());
         $rolesTab = $fields->findOrMakeTab('Root.Roles', _t('SecurityAdmin.TABROLES', 'Roles'));
         $rolesTab->push($rolesField);
     }
     $actionParam = $this->getRequest()->param('Action');
     if ($actionParam == 'groups') {
         $groupsTab->addExtraClass('ui-state-active');
     } elseif ($actionParam == 'users') {
         $usersTab->addExtraClass('ui-state-active');
     } elseif ($actionParam == 'roles' && $rolesTab) {
         $rolesTab->addExtraClass('ui-state-active');
     }
     $actions = new FieldList();
     $form = Form::create($this, 'EditForm', $fields, $actions)->setHTMLID('Form_EditForm');
     $form->addExtraClass('cms-edit-form fill-height');
     $form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
     // Tab nav in CMS is rendered through separate template
     if ($form->Fields()->hasTabSet()) {
         $form->Fields()->findOrMakeTab('Root')->setTemplate('SilverStripe\\Forms\\CMSTabSet');
     }
     $form->addExtraClass('ss-tabset cms-tabset ' . $this->BaseCSSClasses());
     $form->setAttribute('data-pjax-fragment', 'CurrentForm');
     $this->extend('updateEditForm', $form);
     return $form;
 }
 /**
  * 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;
 }