public function testMessagesInsideNestedCompositeFields()
 {
     $fieldGroup = new FieldGroup(new CompositeField($textField = new TextField('TestField', 'Test Field'), $emailField = new EmailField('TestEmailField', 'Test Email Field')));
     $textField->setError('Test error message', 'warning');
     $emailField->setError('Test error message', 'error');
     $this->assertEquals('Test error message,  Test error message.', $fieldGroup->Message());
     $this->assertEquals('warning.  error', $fieldGroup->MessageType());
 }
 /**
  * Tests the TextField Max Length Validation Success
  */
 public function testMaxLengthValidationSuccess()
 {
     $textField = new TextField('TestField');
     $textField->setMaxLength(5);
     $textField->setValue("John");
     // 4 characters, so should pass
     $result = $textField->validate(new RequiredFields());
     $this->assertTrue($result);
 }
 /**
  * Builds a new currency field based on the allowed currencies configured
  *
  * @return FormField
  */
 protected function buildCurrencyField()
 {
     $name = $this->getName();
     $allowedCurrencies = $this->getAllowedCurrencies();
     if ($allowedCurrencies) {
         $field = new DropdownField("{$name}[Currency]", _t('MoneyField.FIELDLABELCURRENCY', 'Currency'), ArrayLib::is_associative($allowedCurrencies) ? $allowedCurrencies : array_combine($allowedCurrencies, $allowedCurrencies));
     } else {
         $field = new TextField("{$name}[Currency]", _t('MoneyField.FIELDLABELCURRENCY', 'Currency'));
     }
     $field->setReadonly($this->isReadonly());
     $field->setDisabled($this->isDisabled());
     return $field;
 }
 public function testLoadDataFromClearMissingFields()
 {
     $form = new Form(new Controller(), 'Form', new FieldList(new HeaderField('MyPlayerHeader', 'My Player'), new TextField('Name'), new TextareaField('Biography'), new DateField('Birthday'), new NumericField('BirthdayYear'), $unrelatedField = new TextField('UnrelatedFormField')), new FieldList());
     $unrelatedField->setValue("random value");
     $captainWithDetails = $this->objFromFixture('FormTest_Player', 'captainWithDetails');
     $captainNoDetails = $this->objFromFixture('FormTest_Player', 'captainNoDetails');
     $form->loadDataFrom($captainWithDetails);
     $this->assertEquals($form->getData(), array('Name' => 'Captain Details', 'Biography' => 'Bio 1', 'Birthday' => '1982-01-01', 'BirthdayYear' => '1982', 'UnrelatedFormField' => 'random value'), 'LoadDataFrom() doesnt overwrite fields not found in the object');
     $captainWithDetails = $this->objFromFixture('FormTest_Player', 'captainNoDetails');
     $team2 = $this->objFromFixture('FormTest_Team', 'team2');
     $form->loadDataFrom($captainWithDetails);
     $form->loadDataFrom($team2, Form::MERGE_CLEAR_MISSING);
     $this->assertEquals($form->getData(), array('Name' => 'Team 2', 'Biography' => '', 'Birthday' => '', 'BirthdayYear' => 0, 'UnrelatedFormField' => null), 'LoadDataFrom() overwrites fields not found in the object with $clearMissingFields=true');
 }
 public function testValidation()
 {
     $field = CompositeField::create($fieldOne = DropdownField::create('A'), $fieldTwo = TextField::create('B'));
     $validator = new RequiredFields();
     $this->assertFalse($field->validate($validator), "Validation fails when child is invalid");
     $fieldOne->setEmptyString('empty');
     $this->assertTrue($field->validate($validator), "Validates when children are valid");
 }
 public function getFields()
 {
     $fields = parent::getFields();
     // Alt text
     $fields->insertBefore('CaptionText', TextField::create('AltText', _t('HTMLEditorField.IMAGEALT', 'Alternative text (alt)'), $this->Title, 80)->setDescription(_t('HTMLEditorField.IMAGEALTTEXTDESC', 'Shown to screen readers or if image can\'t be displayed')));
     // Tooltip
     $fields->insertAfter('AltText', TextField::create('Title', _t('HTMLEditorField.IMAGETITLETEXT', 'Title text (tooltip)'))->setDescription(_t('HTMLEditorField.IMAGETITLETEXTDESC', 'For additional information about the image')));
     return $fields;
 }
 /**
  * {@inheritdoc}
  */
 public function getAttributes()
 {
     $attributes = array('type' => 'password');
     $autocomplete = $this->config()->get('autocomplete');
     if ($autocomplete) {
         $attributes['autocomplete'] = 'on';
     } else {
         $attributes['autocomplete'] = 'off';
     }
     return array_merge(parent::getAttributes(), $attributes);
 }
 protected function getFormFieldAttributesTab($record, $context = [])
 {
     /** @var Tab $tab */
     $tab = parent::getFormFieldAttributesTab($record, $context);
     $alignments = array('leftAlone' => _t('AssetAdmin.AlignmentLeftAlone', 'On the left, on its own.'), 'center' => _t('AssetAdmin.AlignmentCenter', 'Centered, on its own.'), 'left' => _t('AssetAdmin.AlignmentLeft', 'On the left, with text wrapping around.'), 'right' => _t('AssetAdmin.AlignmentRight', 'On the right, with text wrapping around.'));
     $tab->push(DropdownField::create('Alignment', _t('AssetAdmin.Alignment', 'Alignment'), $alignments));
     $tab->push(FieldGroup::create(_t('AssetAdmin.ImageSpecs', 'Dimensions'), TextField::create('InsertWidth', _t('AssetAdmin.ImageWidth', 'Width'))->setMaxLength(5)->addExtraClass('flexbox-area-grow'), TextField::create('InsertHeight', _t('AssetAdmin.ImageHeight', 'Height'))->setMaxLength(5)->addExtraClass('flexbox-area-grow'))->addExtraClass('fill-width'));
     $tab->insertBefore('Caption', TextField::create('AltText', _t('AssetAdmin.AltText', 'Alternative text (alt)'))->setDescription(_t('AssetAdmin.AltTextDescription', 'Shown to screen readers or if image can\'t be displayed')));
     $tab->insertAfter('AltText', TextField::create('TitleTooltip', _t('AssetAdmin.TitleTooltip', 'Title text (tooltip)'))->setDescription(_t('AssetAdmin.TitleTooltipDescription', 'For additional information about the image'))->setValue($record->Title));
     return $tab;
 }
 public function testDefaultClasses()
 {
     Config::nest();
     FormField::config()->update('default_classes', array('class1'));
     $field = new FormField('MyField');
     $this->assertContains('class1', $field->extraClass(), 'Class list does not contain expected class');
     FormField::config()->update('default_classes', array('class1', 'class2'));
     $field = new FormField('MyField');
     $this->assertContains('class1 class2', $field->extraClass(), 'Class list does not contain expected class');
     FormField::config()->update('default_classes', array('class3'));
     $field = new FormField('MyField');
     $this->assertContains('class3', $field->extraClass(), 'Class list does not contain expected class');
     $field->removeExtraClass('class3');
     $this->assertNotContains('class3', $field->extraClass(), 'Class list contains unexpected class');
     TextField::config()->update('default_classes', array('textfield-class'));
     $field = new TextField('MyField');
     //check default classes inherit
     $this->assertContains('class3', $field->extraClass(), 'Class list does not contain inherited class');
     $this->assertContains('textfield-class', $field->extraClass(), 'Class list does not contain expected class');
     Config::unnest();
 }
 public function getCMSFields()
 {
     $path = '/' . dirname($this->getFilename());
     $previewLink = Convert::raw2att($this->PreviewLink());
     $image = "<img src=\"{$previewLink}\" class=\"editor__thumbnail\" />";
     $link = $this->Link();
     $statusTitle = $this->getStatusTitle();
     $statusFlag = "<span class=\"editor__status-flag\">{$statusTitle}</span>";
     $content = Tab::create('Main', HeaderField::create('TitleHeader', $this->Title, 1)->addExtraClass('editor__heading'), LiteralField::create("ImageFull", $image)->addExtraClass('editor__file-preview'), TabSet::create('Editor', Tab::create('Details', TextField::create("Title", $this->fieldLabel('Title')), TextField::create("Name", $this->fieldLabel('Filename')), ReadonlyField::create("Path", _t('AssetTableField.PATH', 'Path'), ($path !== '/.' ? $path : '') . '/'), HTMLReadonlyField::create('ClickableURL', _t('AssetTableField.URL', 'URL'), sprintf('<i class="%s"></i><a href="%s" target="_blank">%s</a>', 'font-icon-link btn--icon-large form-control-static__icon', $link, $link))), Tab::create('Usage', DatetimeField::create("Created", _t('AssetTableField.CREATED', 'First uploaded'))->setReadonly(true), DatetimeField::create("LastEdited", _t('AssetTableField.LASTEDIT', 'Last changed'))->setReadonly(true))), HiddenField::create('ID', $this->ID));
     if ($dimensions = $this->getDimensions()) {
         $content->insertAfter('TitleHeader', LiteralField::create("DisplaySize", sprintf('<div class="editor__specs">%spx, %s %s</div>', $dimensions, $this->getSize(), $statusFlag)));
     } else {
         $content->insertAfter('TitleHeader', LiteralField::create('StatusFlag', $statusFlag));
     }
     $fields = FieldList::create(TabSet::create('Root', $content));
     $this->extend('updateCMSFields', $fields);
     return $fields;
 }
 /**
  * Create tab for file attributes
  *
  * @param File $record
  * @param array $context
  * @return Tab
  */
 protected function getFormFieldAttributesTab($record, $context = [])
 {
     return Tab::create('Placement', LiteralField::create('AttributesDescription', '<p>' . _t('AssetAdmin.AttributesDescription', 'These changes will only affect this particular placement of the file.') . '</p>'), TextField::create('Caption', _t('AssetAdmin.Caption', 'Caption')));
 }
 public function getCMSFields()
 {
     $fields = new FieldList(new TabSet('Root'));
     if ($this->IsInferred) {
         $fields->addFieldToTab('Root.Main', ReadonlyField::create('Name', $this->fieldLabel('Name')));
     } else {
         $fields->addFieldToTab('Root.Main', TextField::create('Name', $this->fieldLabel('Name')));
     }
     if ($this->isInDB()) {
         $fields->addFieldToTab('Root.Main', ReadonlyField::create('State', $this->fieldLabel('State')));
     }
     $this->extend('updateCMSFields', $fields);
     return $fields;
 }
 /**
  * @inheritdoc
  */
 public function updateCMSFields(FieldList $fields)
 {
     $analyticsFields = FieldList::create(TextField::create("GoogleAnalyticsTrackingID", "Google Analytics Tracking ID")->setDescription("e.g. UA-XXXXXX-X"), TextareaField::create("GoogleAnalyticsParameters", "Additional Parameters")->setDescription("<strong>Advanced users only.</strong>\n\t\t\t\t\tIf you do not know what this field does, please leave it blank."), TextareaField::create("GoogleAnalyticsConstructorParameters", "Constructor Parameters")->setDescription("<strong>Advanced users only.</strong>\n\t\t\t\t\tIf you do not know what this field does, please leave it blank. An object to be\n\t\t\t\t\tpassed as an argument to ga.create()"));
     $fields->addFieldToTab('Root', Tab::create('GoogleAnalytics')->setChildren($analyticsFields));
 }
 /**
  *
  * @param GridField $gridField
  * @return string[] - HTML
  */
 public function getHTMLFragments($gridField)
 {
     $dataClass = $gridField->getModelClass();
     $forTemplate = new ArrayData(array());
     $forTemplate->Fields = new FieldList();
     $searchField = new TextField('gridfield_relationsearch', _t('GridField.RelationSearch', "Relation search"));
     $searchField->setAttribute('data-search-url', Controller::join_links($gridField->Link('search')));
     $searchField->setAttribute('placeholder', $this->getPlaceholderText($dataClass));
     $searchField->addExtraClass('relation-search no-change-track action_gridfield_relationsearch');
     $findAction = new GridField_FormAction($gridField, 'gridfield_relationfind', _t('GridField.Find', "Find"), 'find', 'find');
     $findAction->setAttribute('data-icon', 'relationfind');
     $findAction->addExtraClass('action_gridfield_relationfind');
     $addAction = new GridField_FormAction($gridField, 'gridfield_relationadd', _t('GridField.LinkExisting', "Link Existing"), 'addto', 'addto');
     $addAction->setAttribute('data-icon', 'chain--plus');
     $addAction->addExtraClass('action_gridfield_relationadd');
     // If an object is not found, disable the action
     if (!is_int($gridField->State->GridFieldAddRelation(null))) {
         $addAction->setReadonly(true);
     }
     $forTemplate->Fields->push($searchField);
     $forTemplate->Fields->push($findAction);
     $forTemplate->Fields->push($addAction);
     if ($form = $gridField->getForm()) {
         $forTemplate->Fields->setForm($form);
     }
     $template = SSViewer::get_templates_by_class($this, '', __CLASS__);
     return array($this->targetFragment => $forTemplate->renderWith($template));
 }
 /**
  * Return a {@link Form} instance allowing a user to
  * add images and flash objects to the TinyMCE content editor.
  *
  * @return Form
  */
 public function MediaForm()
 {
     // TODO Handle through GridState within field - currently this state set too late to be useful here (during
     // request handling)
     $parentID = $this->getAttachParentID();
     $fileFieldConfig = GridFieldConfig::create()->addComponents(new GridFieldSortableHeader(), new GridFieldFilterHeader(), new GridFieldDataColumns(), new GridFieldPaginator(7), new GridFieldDeleteAction(), new GridFieldDetailForm());
     $fileField = GridField::create('Files', false, null, $fileFieldConfig);
     $fileField->setList($this->getFiles($parentID));
     $fileField->setAttribute('data-selectable', true);
     $fileField->setAttribute('data-multiselect', true);
     /** @var GridFieldDataColumns $columns */
     $columns = $fileField->getConfig()->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldDataColumns');
     $columns->setDisplayFields(array('StripThumbnail' => false, 'Title' => _t('File.Title'), 'Created' => File::singleton()->fieldLabel('Created')));
     $columns->setFieldCasting(array('Created' => 'DBDatetime->Nice'));
     $fromCMS = new CompositeField($select = TreeDropdownField::create('ParentID', "", 'SilverStripe\\Assets\\Folder')->addExtraClass('noborder')->setValue($parentID), $fileField);
     $fromCMS->addExtraClass('content ss-uploadfield htmleditorfield-from-cms');
     $select->addExtraClass('content-select');
     $URLDescription = _t('HTMLEditorField.URLDESCRIPTION', 'Insert videos and images from the web into your page simply by entering the URL of the file. Make sure you have the rights or permissions before sharing media directly from the web.<br /><br />Please note that files are not added to the file store of the CMS but embeds the file from its original location, if for some reason the file is no longer available in its original location it will no longer be viewable on this page.');
     $fromWeb = new CompositeField($description = new LiteralField('URLDescription', '<div class="url-description">' . $URLDescription . '</div>'), $remoteURL = new TextField('RemoteURL', 'http://'), new LiteralField('addURLImage', '<button type="button" class="action ui-action-constructive ui-button field font-icon-plus add-url">' . _t('HTMLEditorField.BUTTONADDURL', 'Add url') . '</button>'));
     $remoteURL->addExtraClass('remoteurl');
     $fromWeb->addExtraClass('content ss-uploadfield htmleditorfield-from-web');
     Requirements::css(ltrim(FRAMEWORK_ADMIN_DIR . '/client/dist/styles/AssetUploadField.css', '/'));
     $computerUploadField = UploadField::create('AssetUploadField', '');
     $computerUploadField->setConfig('previewMaxWidth', 40);
     $computerUploadField->setConfig('previewMaxHeight', 30);
     $computerUploadField->addExtraClass('toolbar toolbar--content ss-assetuploadfield htmleditorfield-from-computer');
     $computerUploadField->removeExtraClass('ss-uploadfield');
     $computerUploadField->setTemplate('SilverStripe\\Forms\\HTMLEditorField_UploadField');
     $computerUploadField->setFolderName(Upload::config()->get('uploads_folder'));
     $defaultPanel = new CompositeField($computerUploadField, $fromCMS);
     $fromWebPanel = new CompositeField($fromWeb);
     $defaultPanel->addExtraClass('htmleditorfield-default-panel');
     $fromWebPanel->addExtraClass('htmleditorfield-web-panel');
     $allFields = new CompositeField($defaultPanel, $fromWebPanel, $editComposite = new CompositeField(new LiteralField('contentEdit', '<div class="content-edit ss-uploadfield-files files"></div>')));
     $allFields->addExtraClass('ss-insert-media');
     $headings = new CompositeField(new LiteralField('Heading', sprintf('<h3 class="htmleditorfield-mediaform-heading insert">%s</h3>', _t('HTMLEditorField.INSERTMEDIA', 'Insert media from')) . sprintf('<h3 class="htmleditorfield-mediaform-heading update">%s</h3>', _t('HTMLEditorField.UpdateMEDIA', 'Update media'))));
     $headings->addExtraClass('cms-content-header');
     $editComposite->addExtraClass('ss-assetuploadfield');
     $fields = new FieldList($headings, $allFields);
     $form = new Form($this->controller, "{$this->name}/MediaForm", $fields, new FieldList());
     $form->unsetValidator();
     $form->disableSecurityToken();
     $form->loadDataFrom($this);
     $form->addExtraClass('htmleditorfield-form htmleditorfield-mediaform cms-dialog-content');
     // Allow other people to extend the fields being added to the imageform
     $this->extend('updateMediaForm', $form);
     return $form;
 }
 /**
  * Build "details" formfield tab
  *
  * @param File $record
  * @param array $context
  * @return Tab
  */
 protected function getFormFieldDetailsTab($record, $context = [])
 {
     return Tab::create('Details', TextField::create('Name', File::singleton()->fieldLabel('Filename')));
 }
 /**
  * Return the FieldList used to edit this folder in the CMS.
  * You can modify this FieldList by subclassing folder, or by creating a {@link DataExtension}
  * and implemeting updateCMSFields(FieldList $fields) on that extension.
  *
  * @return FieldList
  */
 public function getCMSFields()
 {
     // Don't show readonly path until we can implement parent folder selection,
     // it's too confusing when readonly (makes sense for files only).
     $width = (int) Image::config()->get('asset_preview_width');
     $previewLink = Convert::raw2att($this->ScaleMaxWidth($width)->getIcon());
     $image = "<img src=\"{$previewLink}\" class=\"editor__thumbnail\" />";
     $content = Tab::create('Main', HeaderField::create('TitleHeader', $this->Title, 1)->addExtraClass('editor__heading'), LiteralField::create("IconFull", $image)->addExtraClass('editor__file-preview'), TabSet::create('Editor', Tab::create('Details', TextField::create("Name", $this->fieldLabel('Filename')))), HiddenField::create('ID', $this->ID));
     $fields = FieldList::create(TabSet::create('Root', $content));
     $this->extend('updateCMSFields', $fields);
     return $fields;
 }
 /**
  * @return FieldList
  */
 public function getFields()
 {
     $fields = new FieldList(CompositeField::create(CompositeField::create(LiteralField::create("ImageFull", $this->getPreview()))->setName("FilePreviewImage")->addExtraClass('cms-file-info-preview'), CompositeField::create($this->getDetailFields())->setName("FilePreviewData")->addExtraClass('cms-file-info-data'))->setName("FilePreview")->addExtraClass('cms-file-info'), TextField::create('CaptionText', _t('HTMLEditorField.CAPTIONTEXT', 'Caption text')), DropdownField::create('CSSClass', _t('HTMLEditorField.CSSCLASS', 'Alignment / style'), array('leftAlone' => _t('HTMLEditorField.CSSCLASSLEFTALONE', 'On the left, on its own.'), 'center' => _t('HTMLEditorField.CSSCLASSCENTER', 'Centered, on its own.'), 'left' => _t('HTMLEditorField.CSSCLASSLEFT', 'On the left, with text wrapping around.'), 'right' => _t('HTMLEditorField.CSSCLASSRIGHT', 'On the right, with text wrapping around.'))), FieldGroup::create(_t('HTMLEditorField.IMAGEDIMENSIONS', 'Dimensions'), TextField::create('Width', _t('HTMLEditorField.IMAGEWIDTHPX', 'Width'), $this->getInsertWidth())->setMaxLength(5), TextField::create('Height', " x " . _t('HTMLEditorField.IMAGEHEIGHTPX', 'Height'), $this->getInsertHeight())->setMaxLength(5))->addExtraClass('dimensions last'), HiddenField::create('URL', false, $this->getURL()), HiddenField::create('FileID', false, $this->getFileID()));
     return $fields;
 }
 public function getHTMLFragments($gridField)
 {
     $list = $gridField->getList();
     if (!$this->checkDataType($list)) {
         return null;
     }
     /** @var Filterable $list */
     $forTemplate = new ArrayData(array());
     $forTemplate->Fields = new ArrayList();
     $columns = $gridField->getColumns();
     $filterArguments = $gridField->State->GridFieldFilterHeader->Columns->toArray();
     $currentColumn = 0;
     foreach ($columns as $columnField) {
         $currentColumn++;
         $metadata = $gridField->getColumnMetadata($columnField);
         $title = $metadata['title'];
         $fields = new FieldGroup();
         if ($title && $list->canFilterBy($columnField)) {
             $value = '';
             if (isset($filterArguments[$columnField])) {
                 $value = $filterArguments[$columnField];
             }
             $field = new TextField('filter[' . $gridField->getName() . '][' . $columnField . ']', '', $value);
             $field->addExtraClass('grid-field__sort-field');
             $field->addExtraClass('no-change-track');
             $field->setAttribute('placeholder', _t('GridField.FilterBy', "Filter by ") . _t('GridField.' . $metadata['title'], $metadata['title']));
             $fields->push($field);
             $fields->push(GridField_FormAction::create($gridField, 'reset', false, 'reset', null)->addExtraClass('btn font-icon-cancel btn--no-text ss-gridfield-button-reset')->setAttribute('title', _t('GridField.ResetFilter', "Reset"))->setAttribute('id', 'action_reset_' . $gridField->getModelClass() . '_' . $columnField));
         }
         if ($currentColumn == count($columns)) {
             $fields->push(GridField_FormAction::create($gridField, 'filter', false, 'filter', null)->addExtraClass('btn font-icon-search btn--no-text btn--icon-large grid-field__filter-submit ss-gridfield-button-filter')->setAttribute('title', _t('GridField.Filter', "Filter"))->setAttribute('id', 'action_filter_' . $gridField->getModelClass() . '_' . $columnField));
             $fields->push(GridField_FormAction::create($gridField, 'reset', false, 'reset', null)->addExtraClass('btn font-icon-cancel btn--no-text grid-field__filter-clear ss-gridfield-button-close')->setAttribute('title', _t('GridField.ResetFilter', "Reset"))->setAttribute('id', 'action_reset_' . $gridField->getModelClass() . '_' . $columnField));
             $fields->addExtraClass('filter-buttons');
             $fields->addExtraClass('no-change-track');
         }
         $forTemplate->Fields->push($fields);
     }
     $templates = SSViewer::get_templates_by_class($this, '_Row', __CLASS__);
     return array('header' => $forTemplate->renderWith($templates));
 }
 /**
  * FieldList::forTemplate() returns a concatenation of FieldHolder values.
  */
 public function testForTemplate()
 {
     $set = new FieldList($a = new TextField('A'), $b = new TextField('B'));
     $this->assertEquals($a->FieldHolder() . $b->FieldHolder(), $set->forTemplate());
 }
 /**
  * @param mixed $class
  * @return FormField
  */
 public function castedCopy($class)
 {
     /** @var FormField $copy */
     $copy = Injector::inst()->create($class, $this->name);
     if ($copy->hasMethod('setConfig')) {
         /** @var DateField $copy */
         $config = $this->getConfig();
         foreach ($config as $k => $v) {
             $copy->setConfig($k, $v);
         }
     }
     return parent::castedCopy($copy);
 }
 public function castedCopy($class)
 {
     $copy = parent::castedCopy($class);
     if ($copy->hasMethod('setConfig')) {
         $config = $this->getConfig();
         foreach ($config as $k => $v) {
             /** @var TimeField $copy */
             $copy->setConfig($k, $v);
         }
     }
     return $copy;
 }
    /**
     * Constructor
     *
     * @skipUpgrade
     * @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 $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
     *                                     {@link FormAction} objects
     * @param bool $checkCurrentUser If set to TRUE, it will be checked if a
     *                               the user is currently logged in, and if
     *                               so, only a logout button will be rendered
     */
    public function __construct($controller, $name, $fields = null, $actions = null, $checkCurrentUser = true)
    {
        // This is now set on the class directly to make it easier to create subclasses
        // $this->authenticator_class = $authenticatorClassName;
        $customCSS = project() . '/css/member_login.css';
        if (Director::fileExists($customCSS)) {
            Requirements::css($customCSS);
        }
        if (isset($_REQUEST['BackURL'])) {
            $backURL = $_REQUEST['BackURL'];
        } else {
            $backURL = Session::get('BackURL');
        }
        if ($checkCurrentUser && Member::currentUser() && Member::logged_in_session_exists()) {
            $fields = FieldList::create(HiddenField::create("AuthenticationMethod", null, $this->authenticator_class, $this));
            $actions = FieldList::create(FormAction::create("logout", _t('Member.BUTTONLOGINOTHER', "Log in as someone else")));
        } else {
            if (!$fields) {
                $label = Member::singleton()->fieldLabel(Member::config()->unique_identifier_field);
                $fields = FieldList::create(HiddenField::create("AuthenticationMethod", null, $this->authenticator_class, $this), $emailField = TextField::create("Email", $label, null, null, $this), PasswordField::create("Password", _t('Member.PASSWORD', 'Password')));
                if (Security::config()->remember_username) {
                    $emailField->setValue(Session::get('SessionForms.MemberLoginForm.Email'));
                } else {
                    // Some browsers won't respect this attribute unless it's added to the form
                    $this->setAttribute('autocomplete', 'off');
                    $emailField->setAttribute('autocomplete', 'off');
                }
                if (Security::config()->autologin_enabled) {
                    $fields->push(CheckboxField::create("Remember", _t('Member.KEEPMESIGNEDIN', "Keep me signed in"))->setAttribute('title', sprintf(_t('Member.REMEMBERME', "Remember me next time? (for %d days on this device)"), RememberLoginHash::config()->get('token_expiry_days'))));
                }
            }
            if (!$actions) {
                $actions = FieldList::create(FormAction::create('dologin', _t('Member.BUTTONLOGIN', "Log in")), LiteralField::create('forgotPassword', '<p id="ForgotPassword"><a href="' . Security::lost_password_url() . '">' . _t('Member.BUTTONLOSTPASSWORD', "I've lost my password") . '</a></p>'));
            }
        }
        if (isset($backURL)) {
            $fields->push(HiddenField::create('BackURL', 'BackURL', $backURL));
        }
        // Reduce attack surface by enforcing POST requests
        $this->setFormMethod('POST', true);
        parent::__construct($controller, $name, $fields, $actions);
        $this->setValidator(RequiredFields::create('Email', 'Password'));
        // Focus on the email input when the page is loaded
        $js = <<<JS
\t\t\t(function() {
\t\t\t\tvar el = document.getElementById("MemberLoginForm_LoginForm_Email");
\t\t\t\tif(el && el.focus && (typeof jQuery == 'undefined' || jQuery(el).is(':visible'))) el.focus();
\t\t\t})();
JS;
        Requirements::customScript($js, 'MemberLoginFormFieldFocus');
    }