/**
  * Check if the submitted member data is valid (server-side)
  *
  * Check if a member with that email doesn't already exist, or if it does
  * that it is this member.
  *
  * @param array $data Submitted data
  * @return bool Returns TRUE if the submitted data is valid, otherwise
  *              FALSE.
  */
 public function php($data)
 {
     $valid = parent::php($data);
     $identifierField = (string) Member::config()->unique_identifier_field;
     // Only validate identifier field if it's actually set. This could be the case if
     // somebody removes `Email` from the list of required fields.
     if (isset($data[$identifierField])) {
         $id = isset($data['ID']) ? (int) $data['ID'] : 0;
         if (!$id && ($ctrl = $this->form->getController())) {
             // get the record when within GridField (Member editing page in CMS)
             if ($ctrl instanceof GridFieldDetailForm_ItemRequest && ($record = $ctrl->getRecord())) {
                 $id = $record->ID;
             }
         }
         // If there's no ID passed via controller or form-data, use the assigned member (if available)
         if (!$id && ($member = $this->getForMember())) {
             $id = $member->exists() ? $member->ID : 0;
         }
         // set the found ID to the data array, so that extensions can also use it
         $data['ID'] = $id;
         $members = Member::get()->filter($identifierField, $data[$identifierField]);
         if ($id) {
             $members = $members->exclude('ID', $id);
         }
         if ($members->count() > 0) {
             $this->validationError($identifierField, _t('Member.VALIDATIONMEMBEREXISTS', 'A member already exists with the same {identifier}', array('identifier' => Member::singleton()->fieldLabel($identifierField))), 'required');
             $valid = false;
         }
     }
     // Execute the validators on the extensions
     $results = $this->extend('updatePHP', $data, $this->form);
     $results[] = $valid;
     return min($results);
 }
 public function testFieldIsRequired()
 {
     //get the validator
     $requiredFields = new RequiredFields($fieldNames = array('Title', 'Content', 'Image', 'AnotherField'));
     foreach ($fieldNames as $field) {
         $this->assertTrue($requiredFields->fieldIsRequired($field), sprintf("Failed to find '%s' field in required list", $field));
     }
     //add a new field
     $requiredFields->addRequiredField('ExtraField1');
     //check the new field is required
     $this->assertTrue($requiredFields->fieldIsRequired('ExtraField1'), "Failed to find 'ExtraField1' field in required list after adding it to the list");
     //check a non-existant field returns false
     $this->assertFalse($requiredFields->fieldIsRequired('DoesntExist'), "Unexpectedly returned true for a non-existant field");
 }
 /**
  * Add {@link RequiredField} objects together
  *
  * @param RequiredFields $requiredFields
  * @return RequiredFields
  */
 public function appendRequiredFields($requiredFields)
 {
     $this->required = $this->required + ArrayLib::valuekey($requiredFields->getRequired());
     return $this;
 }
    /**
     * 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');
    }